From f0d83767528896f1e8abba0934b0ba5dd8fad74f Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C3=98yvind=20Kol=C3=A5s?= Date: Sat, 27 Aug 2005 23:42:28 +0000 Subject: [PATCH] extensions break free --- ChangeLog | 20 +- Makefile.am | 3 +- babl/babl-component.c | 2 +- babl/babl-conversion.c | 34 +- babl/babl-conversion.h | 15 +- babl/babl-core.c | 35 +- babl/babl-extension.c | 223 ++++ babl/{base/types.c => babl-extension.h} | 13 +- babl/babl-format.c | 2 +- babl/babl-instance.h | 10 + babl/babl-internal.h | 6 +- babl/babl-model.c | 47 +- babl/babl-pixel-format.c | 2 +- babl/babl-sampling.c | 2 +- babl/babl-type.c | 3 +- babl/babl.h | 6 +- babl/base/Makefile.am | 5 +- babl/base/babl-base.c | 3 - babl/base/cpercep.c | 652 ------------ babl/base/cpercep.h | 70 -- babl/base/model-gray.c | 92 +- babl/base/model-rgb.c | 56 +- babl/base/model-ycbcr.c | 33 +- babl/base/models.c | 21 - babl/base/type-float.c | 11 +- babl/base/type-u16.c | 69 +- babl/base/type-u8.c | 87 +- configure.ac | 1 + docs/index-static.html.in | 9 +- extensions/CIE-Lab.c | 1234 +++++++++++++++++++++++ extensions/Makefile.in | 57 ++ extensions/naive-CMYK.c | 198 ++++ tests/float_to_u8.c | 4 +- tests/grayscale_to_rgb.c | 4 +- tests/rgb_to_bgr.c | 4 +- tests/rgb_to_lab_to_rgb.c | 2 +- tests/rgb_to_ycbcr.c | 4 +- tests/rgb_to_ycbcr_to_rgb.c | 4 +- tests/srgb_to_lab_u8.c | 2 +- tests/u8_to_float.c | 4 +- 40 files changed, 1960 insertions(+), 1089 deletions(-) create mode 100644 babl/babl-extension.c rename babl/{base/types.c => babl-extension.h} (74%) delete mode 100644 babl/base/cpercep.c delete mode 100644 babl/base/cpercep.h delete mode 100644 babl/base/models.c create mode 100644 extensions/CIE-Lab.c create mode 100644 extensions/Makefile.in create mode 100644 extensions/naive-CMYK.c diff --git a/ChangeLog b/ChangeLog index 43741d0..aa384e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,16 +1,9 @@ 2005-08-28 Øyvind Kolås - * configure.ac, - * Makefile.am: added extensions subdir - * extensions/Makefile.in: NB: hard-coded installpath to - /home/pippin/.babl/ - * extensions/CIE-Lab.c: moved here from BablBase, contains cpercep.c - and cpercep.h - * extensions/naive-CMYK.c: moved here from BablBase. * babl/babl-component.c: (babl_component_new): s/parameter/argument/ - + * babl/babl-extension.[ch]: the extension class. * babl/babl-model.c: (create_name), (babl_model_new): generate automatic name, allow override with key/value pair. s/parameter/argument/ @@ -42,6 +35,17 @@ * babl/base/type-u16.c, * babl/base/type-u8.c: new conversion API + + * configure.ac, + * Makefile.am: added extensions subdir + * extensions/Makefile.in: NB: hard-coded installpath to + /home/pippin/.babl/ + * extensions/CIE-Lab.c: moved here from BablBase, contains cpercep.c + and cpercep.h + * extensions/naive-CMYK.c: moved here from BablBase. + + * babl/babl-core.[ch]: double and RGBA originating from BablBase. + * docs/index-static.html.in: updated TODO list. * tests/float_to_u8.c, diff --git a/Makefile.am b/Makefile.am index b877b1c..8cfe7e2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,7 +2,8 @@ AUTOMAKE_OPTIONS = foreign SUBDIRS = babl \ tests \ - docs + docs \ + extensions pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = babl.pc diff --git a/babl/babl-component.c b/babl/babl-component.c index 3724d96..5a8e63c 100644 --- a/babl/babl-component.c +++ b/babl/babl-component.c @@ -108,7 +108,7 @@ babl_component_new (const char *name, else { - babl_log ("unhandled parameter '%s' for format '%s'", arg, name); + babl_log ("unhandled argument '%s' for format '%s'", arg, name); exit (-1); } } diff --git a/babl/babl-conversion.c b/babl/babl-conversion.c index 80a4a74..a94da09 100644 --- a/babl/babl-conversion.c +++ b/babl/babl-conversion.c @@ -131,7 +131,7 @@ create_name (Babl *source, Babl *destination) if (babl_extender ()) { - snprintf (buf, 512-1, "%s::%s to %s", BABL(babl_extender())->instance.name, source->instance.name, destination->instance.name); + snprintf (buf, 512-1, "%s : %s to %s", BABL(babl_extender())->instance.name, source->instance.name, destination->instance.name); buf[511]='\0'; } else @@ -143,15 +143,15 @@ create_name (Babl *source, Babl *destination) } Babl * -babl_conversion_new (const char *name, +babl_conversion_new (Babl *source, + Babl *destination, + void *first_arg, ...) { va_list varg; Babl *babl; int id = 0; - Babl *source = NULL; - Babl *destination = NULL; int time_cost = 0; int loss = 0; BablFuncLinear linear = NULL; @@ -159,17 +159,17 @@ babl_conversion_new (const char *name, BablFuncPlanarBit planar_bit = NULL; int got_func = 0; - const char *arg = name; + const char *arg = first_arg; - va_start (varg, name); + assert (BABL_IS_BABL(source)); + assert (BABL_IS_BABL(destination)); + + va_start (varg, first_arg); while (1) { - arg = va_arg (varg, char *); - if (!arg) - break; - else if (!strcmp (arg, "id")) + if (!strcmp (arg, "id")) { id = va_arg (varg, int); } @@ -209,19 +209,15 @@ babl_conversion_new (const char *name, { loss = va_arg (varg, int); } - else if (!strcmp (arg, "source")) - { - source = va_arg (varg, Babl*); - } - else if (!strcmp (arg, "destination")) - { - destination = va_arg (varg, Babl*); - } else { - babl_log ("unhandled parameter '%s' for format '%s'", arg, name); + babl_log ("unhandled argument '%s'", arg); exit (-1); } + + arg = va_arg (varg, char *); + if (!arg) + break; } va_end (varg); diff --git a/babl/babl-conversion.h b/babl/babl-conversion.h index a3d1c6a..50f06c6 100644 --- a/babl/babl-conversion.h +++ b/babl/babl-conversion.h @@ -23,10 +23,15 @@ #include "babl-classes.h" #include "babl-instance.h" -void babl_conversion_process (BablConversion *conversion, - void *source, - void *destination, - long n); +void babl_conversion_process (BablConversion *conversion, + void *source, + void *destination, + long n); -BABL_DEFINE_CLASS (babl_conversion) +Babl * babl_conversion_new (Babl *source, + Babl *destination, + void *first_argument, + ...); + +BABL_DEFINE_CLASS_NO_NEW (babl_conversion); #endif diff --git a/babl/babl-core.c b/babl/babl-core.c index 90cb7ec..8fd50a4 100644 --- a/babl/babl-core.c +++ b/babl/babl-core.c @@ -1,6 +1,26 @@ +/* babl - dynamically extendable universal pixel conversion library. + * Copyright (C) 2005, Øyvind Kolås. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + #include -#include "util.h" #include "babl.h" +#include "babl-ids.h" +#include "util.h" static void convert_double_double (void *src, @@ -62,10 +82,9 @@ babl_core_init (void) NULL); babl_conversion_new ( - "babl-base: double to double", - "source", babl_type_id (BABL_DOUBLE), - "destination", babl_type_id (BABL_DOUBLE), - "linear", convert_double_double, + babl_type_id (BABL_DOUBLE), + babl_type_id (BABL_DOUBLE), + "linear", convert_double_double, NULL ); @@ -97,7 +116,6 @@ babl_core_init (void) NULL); babl_model_new ( - "rgba", "id", BABL_RGBA, babl_component_id (BABL_RED), babl_component_id (BABL_GREEN), @@ -106,9 +124,8 @@ babl_core_init (void) NULL); babl_conversion_new ( - "babl-base: rgba to rgba", - "source", babl_model_id (BABL_RGBA), - "destination", babl_model_id (BABL_RGBA), + babl_model_id (BABL_RGBA), + babl_model_id (BABL_RGBA), "planar", copy_strip_1, NULL ); diff --git a/babl/babl-extension.c b/babl/babl-extension.c new file mode 100644 index 0000000..667817f --- /dev/null +++ b/babl/babl-extension.c @@ -0,0 +1,223 @@ +/* babl - dynamically extendable universal pixel conversion library. + * Copyright (C) 2005, Øyvind Kolås. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#define BABL_DYNAMIC_EXTENSIONS + +#define BABL_INIT_HOOK init_hook(); +#define BABL_DESTROY_HOOK destroy_hook(); + +#ifdef BABL_DYNAMIC_EXTENSIONS + /* must be defined before inclusion of babl-internal.h */ +#undef BABL_INIT_HOOK +#define BABL_INIT_HOOK init_hook();dynamic_init_hook(); +#endif + +#include "babl-internal.h" +#include "babl-db.h" +#include "babl-base.h" +#include +#include + + +static int each_babl_extension_destroy (Babl *babl, void *data); + +Babl *babl_extension_current_extender = NULL; + +Babl * +babl_extender (void) +{ + if (babl_extension_current_extender) + return babl_extension_current_extender; + return NULL; +} + +static void +babl_set_extender (Babl *new_extender) +{ + babl_extension_current_extender = new_extender; +} + +static Babl * +extension_new (const char *path, + void *dl_handle, + void (*destroy) (void)) +{ + Babl *babl; + + babl = babl_malloc (sizeof (BablExtension) + strlen (path) + 1); + babl->instance.name = (void *) babl + sizeof (BablExtension); + strcpy (babl->instance.name, path); + babl->instance.id = 0; + babl->class_type = BABL_EXTENSION; + babl->extension.dl_handle = dl_handle; + babl->extension.destroy = destroy; + + return babl; +} + +static Babl *babl_quiet = NULL; + +Babl * +babl_extension_quiet_log (void) +{ + if (babl_quiet) + return babl_quiet; + babl_quiet = extension_new ("", NULL, NULL); + db_insert (babl_quiet); + return babl_quiet; +} + +Babl * +babl_extension_base (void) +{ + Babl *babl; + void *dl_handle = NULL; + void (*destroy) (void) = NULL; + + babl = extension_new ("BablBase", + dl_handle, + destroy); + babl_set_extender (babl); + babl_base_init (); + + if (db_insert (babl) == babl) + { + babl_set_extender (NULL); + return babl; + } + else + { + each_babl_extension_destroy (babl, NULL); + babl_set_extender (NULL); + return NULL; + } +} + +static void +init_hook (void) +{ + babl_extension_quiet_log (); + babl_set_extender (NULL); +} + +static void +destroy_hook (void) +{ + babl_quiet=NULL; +} + +#ifdef BABL_DYNAMIC_EXTENSIONS + +#include +#include +#include +#include +#include + +#include +#ifndef RTLD_NOW +#define RTLD_NOW 0 +#endif + + +static Babl * +load_failed (Babl *babl) +{ + if (babl) + { + each_babl_extension_destroy (babl, NULL); + } + babl_set_extender (NULL); + return NULL; +} + +Babl * +babl_extension_load (const char *path) +{ + Babl *babl = NULL; + + /* do the actual loading thing */ + void *dl_handle = NULL; + int (*init) (void) = NULL; + void (*destroy) (void) = NULL; + + + dl_handle = dlopen (path, RTLD_NOW); + if (!dl_handle) + { + babl_log ("dlopen() failed:\n\t%s", dlerror ()); + return load_failed (babl); + } + init = dlsym (dl_handle, "init"); + if (!init) + { + babl_log ("\n\tint babl_extension_init() function not found in extenstion '%s'", path); + return load_failed (babl); + } + + destroy = dlsym (dl_handle, "destroy"); + babl = extension_new (path, + dl_handle, + destroy); + + babl_set_extender (babl); + if(init()) + { + babl_log ("babl_extension_init() in extension '%s' failed (return!=0)", path); + return load_failed (babl); + } + + + if (db_insert (babl) == babl) + { + babl_set_extender (NULL); + return babl; + } + else + { + return load_failed (babl); + } +} + +static void +dynamic_init_hook (void) +{ + babl_extension_load ("/home/pippin/.babl/naive-CMYK.so"); + babl_extension_load ("/home/pippin/.babl/CIE-Lab.so"); +} + +#endif + +static int +each_babl_extension_destroy (Babl *babl, + void *data) +{ + if (babl->extension.destroy) + babl->extension.destroy(); +#ifdef BABL_DYNAMIC_EXTENSIONS + if (babl->extension.dl_handle) + dlclose (babl->extension.dl_handle); +#endif + + babl_free (babl); + return 0; /* continue iterating */ +} + + +BABL_CLASS_TEMPLATE (babl_extension) diff --git a/babl/base/types.c b/babl/babl-extension.h similarity index 74% rename from babl/base/types.c rename to babl/babl-extension.h index a9ac707..b344ea2 100644 --- a/babl/base/types.c +++ b/babl/babl-extension.h @@ -17,8 +17,15 @@ * Boston, MA 02111-1307, USA. */ -#include -#include +#ifndef _BABL_EXTENSION_H +#define _BABL_EXTENSION_H -#include "babl.h" +#include "babl-classes.h" +#include "babl-instance.h" +Babl * babl_extension_base (void); +Babl * babl_extender (void); +Babl * babl_extension_quiet_log (void); + +BABL_DEFINE_CLASS (babl_extension) +#endif diff --git a/babl/babl-format.c b/babl/babl-format.c index 5511290..2a53193 100644 --- a/babl/babl-format.c +++ b/babl/babl-format.c @@ -210,7 +210,7 @@ babl_format_new (const char *name, else { - babl_log ("unhandled parameter '%s' for format '%s'", arg, name); + babl_log ("unhandled argument '%s' for format '%s'", arg, name); exit (-1); } } diff --git a/babl/babl-instance.h b/babl/babl-instance.h index 34ee026..809b226 100644 --- a/babl/babl-instance.h +++ b/babl/babl-instance.h @@ -20,6 +20,16 @@ Babl * type_name (const char *name); \ Babl * type_name##_id (int id); \ Babl * type_name##_new (const char *name, \ ...); + + +#define BABL_DEFINE_CLASS_NO_NEW(type_name) \ + \ +void type_name##_init (void); \ +void type_name##_destroy (void); \ +void type_name##_each (BablEachFunction each_fun, \ + void *user_data); \ +Babl * type_name##_id (int id); + #define BABL_DEFINE_CLASS_NO_NEW_NO_ID(type_name) \ \ void type_name##_init (void); \ diff --git a/babl/babl-internal.h b/babl/babl-internal.h index 3b6225f..81842f2 100644 --- a/babl/babl-internal.h +++ b/babl/babl-internal.h @@ -32,11 +32,9 @@ #include "babl-ids.h" #include "babl-util.h" #include "babl-memory.h" -#include "babl-introspect.h" - -#include "babl-classes.h" /* internal classes */ +#include "babl-introspect.h" #include "babl-conversion.h" #include "babl-extension.h" /* */ @@ -87,7 +85,6 @@ const char *babl_class_name (BablClassType klass); void babl_internal_init (void); void babl_internal_destroy (void); -extern int babl_hmpf_on_name_lookups; #define BABL_DEFINE_EACH(type_name) \ void \ @@ -125,6 +122,7 @@ type_name (const char *name) \ if (!babl) \ { \ babl_log ("%s(\"%s\"): not found", __FUNCTION__, name); \ + exit (-1); \ } \ return babl; \ } diff --git a/babl/babl-model.c b/babl/babl-model.c index 159e468..d3f12cf 100644 --- a/babl/babl-model.c +++ b/babl/babl-model.c @@ -33,6 +33,25 @@ each_babl_model_destroy (Babl *babl, return 0; /* continue iterating */ } +static char buf[512]=""; + +static const char * +create_name (const char *name, + int components, + BablComponent **component) +{ + char *p = buf; + if (name) + return name; + while (components--) + { + sprintf (p, (*component)->instance.name); + p+=strlen ((*component)->instance.name); + component++; + } + return buf; +} + static Babl * model_new (const char *name, int id, @@ -59,24 +78,21 @@ model_new (const char *name, } Babl * -babl_model_new (const char *name, - ...) +babl_model_new (void *first_argument, + ...) { va_list varg; Babl *babl; - int id = 0; + int id = 0; int components = 0; + const char *arg = first_argument; + const char *name = NULL; BablComponent *component [BABL_MAX_COMPONENTS]; - const char *arg=name; - - va_start (varg, name); + va_start (varg, first_argument); while (1) { - arg = va_arg (varg, char *); - if (!arg) - break; if (BABL_IS_BABL (arg)) @@ -124,17 +140,26 @@ babl_model_new (const char *name, { id = va_arg (varg, int); } + + else if (!strcmp (arg, "name")) + { + name = va_arg (varg, char *); + } else { - babl_log ("unhandled parameter '%s' for babl_model '%s'", arg, name); + babl_log ("unhandled argument '%s' for babl_model '%s'", arg, name); exit (-1); } + + arg = va_arg (varg, char *); + if (!arg) + break; } va_end (varg); - babl = model_new (name, id, components, component); + babl = model_new (create_name (name, components, component), id, components, component); if (db_insert (babl) == babl) { diff --git a/babl/babl-pixel-format.c b/babl/babl-pixel-format.c index 5511290..2a53193 100644 --- a/babl/babl-pixel-format.c +++ b/babl/babl-pixel-format.c @@ -210,7 +210,7 @@ babl_format_new (const char *name, else { - babl_log ("unhandled parameter '%s' for format '%s'", arg, name); + babl_log ("unhandled argument '%s' for format '%s'", arg, name); exit (-1); } } diff --git a/babl/babl-sampling.c b/babl/babl-sampling.c index e95f87d..7a51d51 100644 --- a/babl/babl-sampling.c +++ b/babl/babl-sampling.c @@ -37,7 +37,7 @@ babl_sampling (int horizontal, horizontal<=4) return &db [ (vertical-1) * 4 + (horizontal-1)]; else - babl_log ("babl_samping(%i,%i): parameters out of bounds", + babl_log ("babl_samping(%i,%i): arguments out of bounds", horizontal, vertical); return NULL; } diff --git a/babl/babl-type.c b/babl/babl-type.c index 6812231..7c8fc0c 100644 --- a/babl/babl-type.c +++ b/babl/babl-type.c @@ -125,8 +125,7 @@ babl_type_new (const char *name, else { - babl_log ("unhandled parameter '%s' for format '%s'", - arg, name); + babl_log ("unhandled argument '%s' for format '%s'", arg, name); exit (-1); } } diff --git a/babl/babl.h b/babl/babl.h index e47eb91..bc0efa3 100644 --- a/babl/babl.h +++ b/babl/babl.h @@ -28,14 +28,14 @@ #include #include "babl-classes.h" +#include "babl-component.h" #include "babl-conversion.h" #include "babl-fish.h" +#include "babl-image.h" #include "babl-model.h" -#include "babl-ids.h" +#include "babl-pixel-format.h" #include "babl-type.h" -#include "babl-component.h" #include "babl-sampling.h" -#include "babl-pixel-format.h" void babl_init (void); void babl_destroy (void); diff --git a/babl/base/Makefile.am b/babl/base/Makefile.am index acfef18..e58d545 100644 --- a/babl/base/Makefile.am +++ b/babl/base/Makefile.am @@ -1,16 +1,13 @@ h_sources = \ - babl-base.h \ - cpercep.h + babl-base.h c_sources = \ babl-base.c \ - cpercep.c \ type-float.c \ type-u8.c \ type-u16.c \ model-rgb.c \ model-gray.c \ - model-lab.c \ model-ycbcr.c INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/babl diff --git a/babl/base/babl-base.c b/babl/base/babl-base.c index ee4ac51..12165b4 100644 --- a/babl/base/babl-base.c +++ b/babl/base/babl-base.c @@ -62,14 +62,11 @@ types (void) void babl_base_model_rgb (void); void babl_base_model_gray (void); void babl_base_model_ycbcr (void); -void babl_base_model_lab (void); static void models (void) { babl_base_model_rgb (); babl_base_model_gray (); - babl_base_model_lab (); babl_base_model_ycbcr (); } - diff --git a/babl/base/cpercep.c b/babl/base/cpercep.c deleted file mode 100644 index 055bf95..0000000 --- a/babl/base/cpercep.c +++ /dev/null @@ -1,652 +0,0 @@ -/* -Copyright (C) 1999-2002 Adam D. Moss (the "Author"). All Rights Reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is fur- -nished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- -NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON- -NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of the Author of the -Software shall not be used in advertising or otherwise to promote the sale, -use or other dealings in this Software without prior written authorization -from the Author. -*/ - -/* - cpercep.c: The CPercep Functions v0.9: 2002-02-10 - Adam D. Moss: adam@gimp.org - - This code module concerns itself with conversion from a hard-coded - RGB colour space (sRGB by default) to CIE L*a*b* and back again with - (primarily) precision and (secondarily) speed, oriented largely - towards the purposes of quantifying the PERCEPTUAL difference between - two arbitrary RGB colours with a minimum of fuss. - - Motivation One: The author is disheartened at the amount of graphics - processing software around which uses weighted or non-weighted - Euclidean distance between co-ordinates within a (poorly-defined) RGB - space as the basis of what should really be an estimate of perceptual - difference to the human eye. Certainly it's fast to do it that way, - but please think carefully about whether your particular application - should be tolerating sloppy results for the sake of real-time response. - - Motivation Two: Lack of tested, re-usable and free code available - for this purpose. The difficulty in finding something similar to - CPercep with a free license motivated this project; I hope that this - code also serves to illustrate how to perform the - R'G'B'->XYZ->L*a*b*->XYZ->R'G'B' transformation correctly since I - was distressed to note how many of the equations and code snippets - on the net were omitting the reverse transform and/or were using - incorrectly-derived or just plain wrong constants. - - TODO: document functions, rename erroneously-named arguments -*/ - -/* defines added to make it compile outside gimp */ - -#ifndef gboolean -#define gboolean int -#endif -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE 1 -#endif - - -#include "config.h" -#include - -#ifndef __GLIBC__ -/* cbrt() is a GNU extension */ -#define cbrt(x) (pow(x, 1.0/3.0)) -#endif - -#include "cpercep.h" - - -/* defines: - - SANITY: emits warnings when passed non-sane colours (and usually - corrects them) -- useful when debugging. - - APPROX: speeds up the conversion from RGB to the colourspace by - assuming that the RGB values passed in are integral and definitely - in the range 0->255 - - SRGB: assumes that the RGB values being passed in (and out) are - destined for an sRGB-alike display device (a typical modern monitor) - -- if you change this then you'll probably want to change ASSUMED_GAMMA, - the phosphor colours and the white point definition. -*/ - -/* #define SANITY */ -/* #define APPROX */ -/* #define SRGB */ - - -#ifdef SRGB -#define ASSUMED_GAMMA (2.2F) -#else -/*#define ASSUMED_GAMMA (2.591F)*/ -#define ASSUMED_GAMMA (1.0F) -#endif - -#define REV_GAMMA ((1.0F / ASSUMED_GAMMA)) - - -/* define characteristics of the source RGB space (and the space - within which we try to behave linearly). */ - -/* Phosphor colours: */ - -/* sRGB/HDTV phosphor colours */ -static const double pxr = 0.64F; -static const double pyr = 0.33F; -static const double pxg = 0.30F; -static const double pyg = 0.60F; -static const double pxb = 0.15F; -static const double pyb = 0.06F; - -/* White point: */ - -/* D65 (6500K) (recommended but not a common display default) */ -static const double lxn = 0.312713F; -static const double lyn = 0.329016F; - -/* D50 (5000K) */ -/*static const double lxn = 0.3457F; */ -/*static const double lyn = 0.3585F; */ - -/* D55 (5500K) */ -/*static const double lxn = 0.3324F; */ -/*static const double lyn = 0.3474F; */ - -/* D93 (9300K) (a common monitor default, but poor colour reproduction) */ -/* static const double lxn = 0.2848F; */ -/* static const double lyn = 0.2932F; */ - -/* illum E (normalized) */ -/*static const double lxn = 1.0/3.0F; */ -/*static const double lyn = 1.0/3.0F; */ - -/* illum C (average sunlight) */ -/*static const double lxn = 0.3101F; */ -/*static const double lyn = 0.3162F; */ - -/* illum B (direct sunlight) */ -/*static const double lxn = 0.3484F; */ -/*static const double lyn = 0.3516F; */ - -/* illum A (tungsten lamp) */ -/*static const double lxn = 0.4476F; */ -/*static const double lyn = 0.4074F; */ - - -static const double LRAMP = 7.99959199F; - - -static double xnn, znn; - -static double powtable[256]; - - -#ifndef CLAMP -#define CLAMP(x,l,u) ((x)<(l)?(l):((x)>(u)?(u):(x))) -#endif - - -static void -init_powtable(const double gamma) -{ - int i; - -#ifndef SRGB - /* pure gamma function */ - for (i=0; i<256; i++) - { - powtable[i] = pow((i)/255.0F, gamma); - } -#else - /* sRGB gamma curve */ - for (i=0; i<11 /* 0.03928 * 255 */; i++) - { - powtable[i] = (i) / (255.0F * 12.92F); - } - for (; i<256; i++) - { - powtable[i] = pow( (((i) / 255.0F) + 0.055F) / 1.055F, 2.4F); - } -#endif -} - - -typedef double CMatrix[3][3]; -typedef double CVector[3]; - -static CMatrix Mrgb_to_xyz, Mxyz_to_rgb; - -static int -Minvert (CMatrix src, CMatrix dest) -{ - double det; - - dest[0][0] = src[1][1] * src[2][2] - src[1][2] * src[2][1]; - dest[0][1] = src[0][2] * src[2][1] - src[0][1] * src[2][2]; - dest[0][2] = src[0][1] * src[1][2] - src[0][2] * src[1][1]; - dest[1][0] = src[1][2] * src[2][0] - src[1][0] * src[2][2]; - dest[1][1] = src[0][0] * src[2][2] - src[0][2] * src[2][0]; - dest[1][2] = src[0][2] * src[1][0] - src[0][0] * src[1][2]; - dest[2][0] = src[1][0] * src[2][1] - src[1][1] * src[2][0]; - dest[2][1] = src[0][1] * src[2][0] - src[0][0] * src[2][1]; - dest[2][2] = src[0][0] * src[1][1] - src[0][1] * src[1][0]; - - det = - src[0][0] * dest[0][0] + - src[0][1] * dest[1][0] + - src[0][2] * dest[2][0]; - - if (det <= 0.0F) - { -#ifdef SANITY - g_printerr ("\n\007 XXXX det: %f\n", det); -#endif - return 0; - } - - dest[0][0] /= det; - dest[0][1] /= det; - dest[0][2] /= det; - dest[1][0] /= det; - dest[1][1] /= det; - dest[1][2] /= det; - dest[2][0] /= det; - dest[2][1] /= det; - dest[2][2] /= det; - - return 1; -} - - -static void -rgbxyzrgb_init(void) -{ - init_powtable (ASSUMED_GAMMA); - - xnn = lxn / lyn; - /* ynn taken as 1.0 */ - znn = (1.0F - (lxn + lyn)) / lyn; - - { - CMatrix MRC, MRCi; - double C1,C2,C3; - - MRC[0][0] = pxr; - MRC[0][1] = pxg; - MRC[0][2] = pxb; - MRC[1][0] = pyr; - MRC[1][1] = pyg; - MRC[1][2] = pyb; - MRC[2][0] = 1.0F - (pxr + pyr); - MRC[2][1] = 1.0F - (pxg + pyg); - MRC[2][2] = 1.0F - (pxb + pyb); - - Minvert (MRC, MRCi); - - C1 = MRCi[0][0]*xnn + MRCi[0][1] + MRCi[0][2]*znn; - C2 = MRCi[1][0]*xnn + MRCi[1][1] + MRCi[1][2]*znn; - C3 = MRCi[2][0]*xnn + MRCi[2][1] + MRCi[2][2]*znn; - - Mrgb_to_xyz[0][0] = MRC[0][0] * C1; - Mrgb_to_xyz[0][1] = MRC[0][1] * C2; - Mrgb_to_xyz[0][2] = MRC[0][2] * C3; - Mrgb_to_xyz[1][0] = MRC[1][0] * C1; - Mrgb_to_xyz[1][1] = MRC[1][1] * C2; - Mrgb_to_xyz[1][2] = MRC[1][2] * C3; - Mrgb_to_xyz[2][0] = MRC[2][0] * C1; - Mrgb_to_xyz[2][1] = MRC[2][1] * C2; - Mrgb_to_xyz[2][2] = MRC[2][2] * C3; - - Minvert (Mrgb_to_xyz, Mxyz_to_rgb); - } -} - - -static void -xyz_to_rgb (double *inx_outr, - double *iny_outg, - double *inz_outb) -{ - const double x = *inx_outr; - const double y = *iny_outg; - const double z = *inz_outb; - - *inx_outr = Mxyz_to_rgb[0][0]*x + Mxyz_to_rgb[0][1]*y + Mxyz_to_rgb[0][2]*z; - *iny_outg = Mxyz_to_rgb[1][0]*x + Mxyz_to_rgb[1][1]*y + Mxyz_to_rgb[1][2]*z; - *inz_outb = Mxyz_to_rgb[2][0]*x + Mxyz_to_rgb[2][1]*y + Mxyz_to_rgb[2][2]*z; -} - - -static void -rgb_to_xyz (double *inr_outx, - double *ing_outy, - double *inb_outz) -{ - const double r = *inr_outx; - const double g = *ing_outy; - const double b = *inb_outz; - - *inr_outx = Mrgb_to_xyz[0][0]*r + Mrgb_to_xyz[0][1]*g + Mrgb_to_xyz[0][2]*b; - *ing_outy = Mrgb_to_xyz[1][0]*r + Mrgb_to_xyz[1][1]*g + Mrgb_to_xyz[1][2]*b; - *inb_outz = Mrgb_to_xyz[2][0]*r + Mrgb_to_xyz[2][1]*g + Mrgb_to_xyz[2][2]*b; -} - - -static inline double -ffunc(const double t) -{ - if (t > 0.008856F) - { - return (cbrt(t)); - } - else - { - return (7.787F * t + 16.0F/116.0F); - } -} - - -static inline double -ffunc_inv(const double t) -{ - if (t > 0.206893F) - { - return (t * t * t); - } - else - { - return ((t - 16.0F/116.0F) / 7.787F); - } -} - - -static void -xyz_to_lab (double *inx, - double *iny, - double *inz) -{ - double L,a,b; - double ffuncY; - const double X = *inx; - const double Y = *iny; - const double Z = *inz; - - if (Y > 0.0F) - { - if (Y > 0.008856F) - { - L = (116.0F * cbrt(Y)) - 16.0F; - } - else - { - L = (Y * 903.3F); - } - -#ifdef SANITY - if (L < 0.0F) - { - g_printerr (" %f \007",(float)L); - } - - if (L > 100.0F) - { - g_printerr (" %f \007",(float)L); - } -#endif - } - else - { - L = 0.0; - } - - ffuncY = ffunc(Y); - a = 500.0F * (ffunc(X/xnn) - ffuncY); - b = 200.0F * (ffuncY - ffunc(Z/znn)); - - *inx = L; - *iny = a; - *inz = b; -} - - -static void -lab_to_xyz (double *inl, - double *ina, - double *inb) -{ - double X,Y,Z; - double P; - const double L = *inl; - const double a = *ina; - const double b = *inb; - - if (L > LRAMP) - { - P = Y = (L + 16.0F) / 116.0F; - Y = Y * Y * Y; - } - else - { - Y = L / 903.3F; - P = 7.787F * Y + 16.0F/116.0F; - } - - X = (P + a / 500.0F); - X = xnn * ffunc_inv(X); - Z = (P - b / 200.0F); - Z = znn * ffunc_inv(Z); - -#ifdef SANITY - if (X<-0.00000F) - { - if (X<-0.0001F) - g_printerr ("{badX %f {%f,%f,%f}}",X,L,a,b); - X = 0.0F; - } - if (Y<-0.00000F) - { - if (Y<-0.0001F) - g_printerr ("{badY %f}",Y); - Y = 0.0F; - } - if (Z<-0.00000F) - { - if (Z<-0.1F) - g_printerr ("{badZ %f}",Z); - Z = 0.0F; - } -#endif - - *inl = X; - *ina = Y; - *inb = Z; -} - - - -/* call this before using the CPercep function */ -void -cpercep_init (void) -{ - static gboolean initialized = FALSE; - - if (! initialized) - { - rgbxyzrgb_init(); - initialized = TRUE; - } -} - -void -cpercep_rgb_to_space (double inr, - double ing, - double inb, - double *outr, - double *outg, - double *outb) -{ -#ifdef APPROX -#ifdef SANITY - /* ADM extra sanity */ - if ((inr) > 255.0F || - (ing) > 255.0F || - (inb) > 255.0F || - (inr) < -0.0F || - (ing) < -0.0F || - (inb) < -0.0F - ) - abort(); -#endif /* SANITY */ - inr = powtable[(int)inr]; - ing = powtable[(int)ing]; - inb = powtable[(int)inb]; -#else -#ifdef SRGB - /* sRGB gamma curve */ - if (inr <= (0.03928F * 255.0F)) - inr = inr / (255.0F * 12.92F); - else - inr = pow( (inr + (0.055F * 255.0F)) / (1.055F * 255.0F), 2.4F); - - if (ing <= (0.03928F * 255.0F)) - ing = ing / (255.0F * 12.92F); - else - ing = pow( (ing + (0.055F * 255.0F)) / (1.055F * 255.0F), 2.4F); - - if (inb <= (0.03928F * 255.0F)) - inb = inb / (255.0F * 12.92F); - else - inb = pow( (inb + (0.055F * 255.0F)) / (1.055F * 255.0F), 2.4F); -#else - /* pure gamma function */ - - /* babl uses normalized RGB - inr = pow((inr)/255.0F, ASSUMED_GAMMA); - ing = pow((ing)/255.0F, ASSUMED_GAMMA); - inb = pow((inb)/255.0F, ASSUMED_GAMMA); - */ -#endif /* SRGB */ -#endif /* APPROX */ - -#ifdef SANITY - /* ADM extra sanity */ - if ((inr) > 1.0F || - (ing) > 1.0F || - (inb) > 1.0F || - (inr) < 0.0F || - (ing) < 0.0F || - (inb) < 0.0F - ) - { - g_printerr ("%%"); - /* abort(); */ - } -#endif /* SANITY */ - - rgb_to_xyz(&inr, &ing, &inb); - -#ifdef SANITY - if (inr < 0.0F || ing < 0.0F || inb < 0.0F) - { - g_printerr (" [BAD2 XYZ: %f,%f,%f]\007 ", - inr,ing,inb); - } -#endif /* SANITY */ - - xyz_to_lab(&inr, &ing, &inb); - - *outr = inr; - *outg = ing; - *outb = inb; -} - - -void -cpercep_space_to_rgb (double inr, - double ing, - double inb, - double *outr, - double *outg, - double *outb) -{ - lab_to_xyz(&inr, &ing, &inb); - -#ifdef SANITY - if (inr<-0.0F || ing<-0.0F || inb<-0.0F) - { - g_printerr (" [BAD1 XYZ: %f,%f,%f]\007 ", - inr,ing,inb); - } -#endif - - xyz_to_rgb(&inr, &ing, &inb); - - /* yes, essential. :( */ - inr = CLAMP(inr,0.0F,1.0F); - ing = CLAMP(ing,0.0F,1.0F); - inb = CLAMP(inb,0.0F,1.0F); - -#ifdef SRGB - if (inr <= 0.0030402477F) - inr = inr * (12.92F * 255.0F); - else - inr = pow(inr, 1.0F/2.4F) * (1.055F * 255.0F) - (0.055F * 255.0F); - - if (ing <= 0.0030402477F) - ing = ing * (12.92F * 255.0F); - else - ing = pow(ing, 1.0F/2.4F) * (1.055F * 255.0F) - (0.055F * 255.0F); - - if (inb <= 0.0030402477F) - inb = inb * (12.92F * 255.0F); - else - inb = pow(inb, 1.0F/2.4F) * (1.055F * 255.0F) - (0.055F * 255.0F); -#else - /* babl uses normalized RGB values - inr = 255.0F * pow(inr, REV_GAMMA); - ing = 255.0F * pow(ing, REV_GAMMA); - inb = 255.0F * pow(inb, REV_GAMMA); - */ -#endif - - *outr = inr; - *outg = ing; - *outb = inb; -} - - -#if 0 -/* EXPERIMENTAL SECTION */ - -const double -xscaler(const double start, const double end, - const double me, const double him) -{ - return start + ((end-start) * him) / (me + him); -} - - -void -mix_colours (const double L1, const double a1, const double b1, - const double L2, const double a2, const double b2, - double *rtnL, double *rtna, double *rtnb, - double mass1, double mass2) -{ - double w1, w2; - -#if 0 - *rtnL = xscaler (L1, L2, mass1, mass2); - *rtna = xscaler (a1, a2, mass1, mass2); - *rtnb = xscaler (b1, b2, mass1, mass2); -#else - -#if 1 - w1 = mass1 * L1; - w2 = mass2 * L2; -#else - w1 = mass1 * (L1*L1*L1); - w2 = mass2 * (L2*L2*L2); -#endif - - *rtnL = xscaler (L1, L2, mass1, mass2); - - if (w1 <= 0.0 && - w2 <= 0.0) - { - *rtna = - *rtnb = 0.0; -#ifdef SANITY - /* g_printerr ("\007OUCH. "); */ -#endif - } - else - { - *rtna = xscaler(a1, a2, w1, w2); - *rtnb = xscaler(b1, b2, w1, w2); - } -#endif -} -#endif /* EXPERIMENTAL SECTION */ diff --git a/babl/base/cpercep.h b/babl/base/cpercep.h deleted file mode 100644 index 82bc5c0..0000000 --- a/babl/base/cpercep.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -Copyright (C) 1997-2002 Adam D. Moss (the "Author"). All Rights Reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is fur- -nished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- -NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON- -NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of the Author of the -Software shall not be used in advertising or otherwise to promote the sale, -use or other dealings in this Software without prior written authorization -from the Author. -*/ - -/* - cpercep.c: The CPercep Functions v0.9: 2002-02-10 - Adam D. Moss: adam@gimp.org - - TODO: document functions, rename erroneously-named arguments -*/ - -#ifndef __CPERCEP_H__ -#define __CPERCEP_H__ - - -void cpercep_init (void); - -void cpercep_rgb_to_space (double inr, - double ing, - double inb, - double *outr, - double *outg, - double *outb); - -void cpercep_space_to_rgb (double inr, - double ing, - double inb, - double *outr, - double *outg, - double *outb); - - -#if 0 -/* This is in the header so that it can potentially be inlined. */ -static const double -cpercep_distance_space (const double L1, const double a1, const double b1, - const double L2, const double a2, const double b2) -{ - const double Ld = L1 - L2; - const double ad = a1 - a2; - const double bd = b1 - b2; - - return (Ld*Ld + ad*ad + bd*bd); -} -#endif - - -#endif /* __CPERCEP_H__ */ diff --git a/babl/base/model-gray.c b/babl/base/model-gray.c index 4a61764..d8097bd 100644 --- a/babl/base/model-gray.c +++ b/babl/base/model-gray.c @@ -20,6 +20,7 @@ /* FIXME: this file should be renamed model-gray.c */ #include "babl.h" +#include "babl-ids.h" #include "util.h" #include "rgb-constants.h" #include "math.h" @@ -45,7 +46,7 @@ components (void) NULL); babl_component_new ( - "Y*A", + "Ya", "id", BABL_LUMINANCE_MUL_ALPHA, "luma", NULL); @@ -61,38 +62,32 @@ static void models (void) { babl_model_new ( - "gray", "id", BABL_GRAY, babl_component_id (BABL_LUMINANCE), NULL); babl_model_new ( - "gray'", "id", BABL_GRAY_GAMMA_2_2, babl_component_id (BABL_LUMINANCE_GAMMA_2_2), NULL); babl_model_new ( - "gray'a", "id", BABL_GRAY_GAMMA_2_2_ALPHA, babl_component_id (BABL_LUMINANCE_GAMMA_2_2), babl_component_id (BABL_ALPHA), NULL); babl_model_new ( - "graya", "id", BABL_GRAY_ALPHA, babl_component_id (BABL_LUMINANCE), babl_component_id (BABL_ALPHA), NULL); babl_model_new ( - "grayA", "id", BABL_GRAY_ALPHA_PREMULTIPLIED, babl_component_id (BABL_LUMINANCE_MUL_ALPHA), babl_component_id (BABL_ALPHA), NULL); - } @@ -376,130 +371,113 @@ static void conversions (void) { babl_conversion_new ( - "babl-base: gray' to rgba", - "source", babl_model_id (BABL_GRAY_GAMMA_2_2), - "destination", babl_model_id (BABL_RGBA), + babl_model_id (BABL_GRAY_GAMMA_2_2), + babl_model_id (BABL_RGBA), "planar", gray_2_2_to_rgb, NULL ); - babl_conversion_new ( - "babl-base: rgba to gray'", - "source", babl_model_id (BABL_RGBA), - "destination", babl_model_id (BABL_GRAY_GAMMA_2_2), + babl_model_id (BABL_RGBA), + babl_model_id (BABL_GRAY_GAMMA_2_2), "planar", rgb_to_gray_2_2, NULL ); babl_conversion_new ( - "babl-base: gray'a to rgba", - "source", babl_model_id (BABL_GRAY_GAMMA_2_2_ALPHA), - "destination", babl_model_id (BABL_RGBA), + babl_model_id (BABL_GRAY_GAMMA_2_2_ALPHA), + babl_model_id (BABL_RGBA), "planar", gray_2_2_to_rgb, NULL ); babl_conversion_new ( - "babl-base: rgba to gray'a", - "source", babl_model_id (BABL_RGBA), - "destination", babl_model_id (BABL_GRAY_GAMMA_2_2_ALPHA), + babl_model_id (BABL_RGBA), + babl_model_id (BABL_GRAY_GAMMA_2_2_ALPHA), "planar", rgb_to_gray_2_2, NULL ); babl_conversion_new ( - "babl-base: gray to rgba", - "source", babl_model_id (BABL_GRAY), - "destination", babl_model_id (BABL_RGBA), + babl_model_id (BABL_GRAY), + babl_model_id (BABL_RGBA), "planar", gray_to_rgb, NULL ); babl_conversion_new ( - "babl-base: gray to rgb", - "source", babl_model_id (BABL_GRAY), - "destination", babl_model_id (BABL_RGB), + babl_model_id (BABL_GRAY), + babl_model_id (BABL_RGB), "planar", gray_to_rgb, NULL ); babl_conversion_new ( - "babl-base: gray-alpha to rgba", - "source", babl_model_id (BABL_GRAY_ALPHA), - "destination", babl_model_id (BABL_RGBA), + babl_model_id (BABL_GRAY_ALPHA), + babl_model_id (BABL_RGBA), "planar", gray_to_rgb, NULL ); babl_conversion_new ( - "babl-base: gray-alpha to rgb", - "source", babl_model_id (BABL_GRAY_ALPHA), - "destination", babl_model_id (BABL_RGB), + babl_model_id (BABL_GRAY_ALPHA), + babl_model_id (BABL_RGB), "planar", gray_to_rgb, NULL ); babl_conversion_new ( - "babl-base: rgba to gray-alpha", - "source", babl_model_id (BABL_RGBA), - "destination", babl_model_id (BABL_GRAY_ALPHA), + babl_model_id (BABL_RGBA), + babl_model_id (BABL_GRAY_ALPHA), "planar", rgb_to_gray, NULL ); babl_conversion_new ( - "babl-base: rgba to gray", - "source", babl_model_id (BABL_RGBA), - "destination", babl_model_id (BABL_GRAY), + babl_model_id (BABL_RGBA), + babl_model_id (BABL_GRAY), "planar", rgb_to_gray, NULL ); babl_conversion_new ( - "babl-base: rgb to gray-alpha", - "source", babl_model_id (BABL_RGB), - "destination", babl_model_id (BABL_GRAY_ALPHA), + babl_model_id (BABL_RGB), + babl_model_id (BABL_GRAY_ALPHA), "planar", rgb_to_gray, NULL ); babl_conversion_new ( - "babl-base: rgb to gray", - "source", babl_model_id (BABL_RGB), - "destination", babl_model_id (BABL_GRAY), + babl_model_id (BABL_RGB), + babl_model_id (BABL_GRAY), "planar", rgb_to_gray, NULL ); babl_conversion_new ( - "babl-base: gray-alpha to gray-alpha-premultiplied", - "source", babl_model_id (BABL_GRAY_ALPHA), - "destination", babl_model_id (BABL_GRAY_ALPHA_PREMULTIPLIED), + babl_model_id (BABL_GRAY_ALPHA), + babl_model_id (BABL_GRAY_ALPHA_PREMULTIPLIED), "planar", non_premultiplied_to_premultiplied, NULL ); babl_conversion_new ( - "babl-base: gray-alpha-premultuplied to gray-alpha", - "source", babl_model_id (BABL_GRAY_ALPHA_PREMULTIPLIED), - "destination", babl_model_id (BABL_GRAY_ALPHA), + babl_model_id (BABL_GRAY_ALPHA_PREMULTIPLIED), + babl_model_id (BABL_GRAY_ALPHA), "planar", premultiplied_to_non_premultiplied, NULL ); - babl_conversion_new ( - "babl-base: gray-alpha-premultiplied to rgba", - "source", babl_model_id (BABL_GRAY_ALPHA_PREMULTIPLIED), - "destination", babl_model_id (BABL_RGBA), + babl_conversion_new ( + babl_model_id (BABL_GRAY_ALPHA_PREMULTIPLIED), + babl_model_id (BABL_RGBA), "planar", gray_alpha_premultiplied_to_rgba, NULL ); babl_conversion_new ( - "babl-base: rgba to gray-alpha-premultiplied", - "source", babl_model_id (BABL_RGBA), - "destination", babl_model_id (BABL_GRAY_ALPHA_PREMULTIPLIED), + babl_model_id (BABL_RGBA), + babl_model_id (BABL_GRAY_ALPHA_PREMULTIPLIED), "planar", rgba_to_gray_alpha_premultiplied, NULL ); diff --git a/babl/base/model-rgb.c b/babl/base/model-rgb.c index e76461f..73673f9 100644 --- a/babl/base/model-rgb.c +++ b/babl/base/model-rgb.c @@ -19,6 +19,7 @@ #include #include "babl.h" +#include "babl-ids.h" #include "util.h" static void models (void); @@ -62,21 +63,21 @@ components (void) babl_component_new ( - "R*A", + "Ra", "id", BABL_RED_MUL_ALPHA, "luma", "chroma", "alpha", NULL); babl_component_new ( - "G*A", + "Ga", "id", BABL_GREEN_MUL_ALPHA, "luma", "chroma", "alpha", NULL); babl_component_new ( - "B*A", + "Ba", "id", BABL_BLUE_MUL_ALPHA, "luma", "chroma", @@ -90,7 +91,6 @@ models (void) { babl_model_new ( - "rgb", "id", BABL_RGB, babl_component_id (BABL_RED), babl_component_id (BABL_GREEN), @@ -98,7 +98,6 @@ models (void) NULL); babl_model_new ( - "rgbA", "id", BABL_RGBA_PREMULTIPLIED, babl_component_id (BABL_RED_MUL_ALPHA), babl_component_id (BABL_GREEN_MUL_ALPHA), @@ -107,7 +106,6 @@ models (void) NULL); babl_model_new ( - "rgb'", "id", BABL_RGB_GAMMA_2_2, babl_component_id (BABL_RED_GAMMA_2_2), babl_component_id (BABL_GREEN_GAMMA_2_2), @@ -115,7 +113,6 @@ models (void) NULL); babl_model_new ( - "rgb'a", "id", BABL_RGBA_GAMMA_2_2, babl_component_id (BABL_RED_GAMMA_2_2), babl_component_id (BABL_GREEN_GAMMA_2_2), @@ -270,73 +267,64 @@ static void conversions (void) { babl_conversion_new ( - "babl-base: rgba to rgba", - "source", babl_model_id (BABL_RGBA), - "destination", babl_model_id (BABL_RGBA), + babl_model_id (BABL_RGBA), + babl_model_id (BABL_RGBA), "planar", copy_strip_1, NULL ); babl_conversion_new ( - "babl-base: rgba to rgb-g2.2", - "source", babl_model_id (BABL_RGBA), - "destination", babl_model_id (BABL_RGB_GAMMA_2_2), + babl_model_id (BABL_RGBA), + babl_model_id (BABL_RGB_GAMMA_2_2), "planar", g3_gamma_2_2, NULL ); babl_conversion_new ( - "babl-base: rgba to rgba-g2.2", - "source", babl_model_id (BABL_RGBA), - "destination", babl_model_id (BABL_RGBA_GAMMA_2_2), + babl_model_id (BABL_RGBA), + babl_model_id (BABL_RGBA_GAMMA_2_2), "planar", g3_gamma_2_2, NULL ); babl_conversion_new ( - "babl-base: rgb-g2.2 to rgba", - "source", babl_model_id (BABL_RGB_GAMMA_2_2), - "destination", babl_model_id (BABL_RGBA), + babl_model_id (BABL_RGB_GAMMA_2_2), + babl_model_id (BABL_RGBA), "planar", g3_inv_gamma_2_2, NULL ); babl_conversion_new ( - "babl-base: rgba-g2.2 to rgba", - "source", babl_model_id (BABL_RGBA_GAMMA_2_2), - "destination", babl_model_id (BABL_RGBA), + babl_model_id (BABL_RGBA_GAMMA_2_2), + babl_model_id (BABL_RGBA), "planar", g3_inv_gamma_2_2, NULL ); babl_conversion_new ( - "babl-base: rgb to rgba", - "source", babl_model_id (BABL_RGB), - "destination", babl_model_id (BABL_RGBA), + babl_model_id (BABL_RGB), + babl_model_id (BABL_RGBA), "planar", copy_strip_1, NULL ); babl_conversion_new ( - "babl-base: rgba to rgb", - "source", babl_model_id (BABL_RGBA), - "destination", babl_model_id (BABL_RGB), + babl_model_id (BABL_RGBA), + babl_model_id (BABL_RGB), "planar", copy_strip_1, NULL ); babl_conversion_new ( - "babl-base: rgba to rgbA", - "source", babl_model_id (BABL_RGBA), - "destination", babl_model_id (BABL_RGBA_PREMULTIPLIED), + babl_model_id (BABL_RGBA), + babl_model_id (BABL_RGBA_PREMULTIPLIED), "planar", non_premultiplied_to_premultiplied, NULL ); babl_conversion_new ( - "babl-base: rgbA to rgba", - "source", babl_model_id (BABL_RGBA_PREMULTIPLIED), - "destination", babl_model_id (BABL_RGBA), + babl_model_id (BABL_RGBA_PREMULTIPLIED), + babl_model_id (BABL_RGBA), "planar", premultiplied_to_non_premultiplied, NULL ); diff --git a/babl/base/model-ycbcr.c b/babl/base/model-ycbcr.c index 6743198..209b9de 100644 --- a/babl/base/model-ycbcr.c +++ b/babl/base/model-ycbcr.c @@ -21,6 +21,7 @@ #include #include #include "babl.h" +#include "babl-ids.h" #include "util.h" @@ -58,7 +59,6 @@ static void models (void) { babl_model_new ( - "y'cbcr", "id", BABL_YCBCR, babl_component_id (BABL_LUMINANCE_GAMMA_2_2), babl_component_id (BABL_CB), @@ -66,7 +66,6 @@ models (void) NULL); babl_model_new ( - "y'cbcra", "id", BABL_YCBCR_ALPHA, babl_component_id (BABL_LUMINANCE_GAMMA_2_2), babl_component_id (BABL_CB), @@ -155,44 +154,38 @@ static void conversions (void) { babl_conversion_new ( - "babl-base: rgba to y'cbcr", - "source", babl_model_id (BABL_RGBA), - "destination", babl_model_id (BABL_YCBCR), + babl_model_id (BABL_RGBA), + babl_model_id (BABL_YCBCR), "planar", rgb_to_ycbcr, NULL ); babl_conversion_new ( - "babl-base: y'cbcr to rgba", - "source", babl_model_id (BABL_YCBCR), - "destination", babl_model_id (BABL_RGBA), + babl_model_id (BABL_YCBCR), + babl_model_id (BABL_RGBA), "planar", ycbcr_to_rgb, NULL ); babl_conversion_new ( - "babl-base: rgb to y'cbcr", - "source", babl_model_id (BABL_RGB), - "destination", babl_model_id (BABL_YCBCR), + babl_model_id (BABL_RGB), + babl_model_id (BABL_YCBCR), "planar", rgb_to_ycbcr, NULL ); babl_conversion_new ( - "babl-base: y'cbcr to rgb", - "source", babl_model_id (BABL_YCBCR), - "destination", babl_model_id (BABL_RGB), + babl_model_id (BABL_YCBCR), + babl_model_id (BABL_RGB), "planar", ycbcr_to_rgb, NULL ); babl_conversion_new ( - "babl-base: rgba to y'cbcra", - "source", babl_model_id (BABL_RGBA), - "destination", babl_model_id (BABL_YCBCR_ALPHA), + babl_model_id (BABL_RGBA), + babl_model_id (BABL_YCBCR_ALPHA), "planar", rgb_to_ycbcr, NULL ); babl_conversion_new ( - "babl-base: y'cbcra to rgba", - "source", babl_model_id (BABL_YCBCR_ALPHA), - "destination", babl_model_id (BABL_RGBA), + babl_model_id (BABL_YCBCR_ALPHA), + babl_model_id (BABL_RGBA), "planar", ycbcr_to_rgb, NULL ); diff --git a/babl/base/models.c b/babl/base/models.c deleted file mode 100644 index 0202888..0000000 --- a/babl/base/models.c +++ /dev/null @@ -1,21 +0,0 @@ -/* babl - dynamically extendable universal pixel conversion library. - * Copyright (C) 2005, Øyvind Kolås. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "babl.h" - diff --git a/babl/base/type-float.c b/babl/base/type-float.c index 6b44146..10576f8 100644 --- a/babl/base/type-float.c +++ b/babl/base/type-float.c @@ -21,6 +21,7 @@ #include #include "babl.h" +#include "babl-ids.h" static void convert_double_float (void *src, @@ -62,17 +63,15 @@ babl_base_type_float (void) NULL); babl_conversion_new ( - "babl-base: float to double", - "source", babl_type_id (BABL_FLOAT), - "destination", babl_type_id (BABL_DOUBLE), + babl_type_id (BABL_FLOAT), + babl_type_id (BABL_DOUBLE), "linear", convert_float_double, NULL ); babl_conversion_new ( - "babl-base: double to float", - "source", babl_type_id (BABL_DOUBLE), - "destination", babl_type_id (BABL_FLOAT), + babl_type_id (BABL_DOUBLE), + babl_type_id (BABL_FLOAT), "linear", convert_double_float, NULL ); diff --git a/babl/base/type-u16.c b/babl/base/type-u16.c index 00b6207..e26f475 100644 --- a/babl/base/type-u16.c +++ b/babl/base/type-u16.c @@ -21,6 +21,7 @@ #include #include "babl.h" +#include "babl-ids.h" static inline void @@ -105,10 +106,6 @@ convert_double_##name (void *src, \ MAKE_CONVERSIONS(u16,0.0,1.0,0,0xffff); -/* source ICC.1:2004-10 */ -MAKE_CONVERSIONS (u16_l, 0.0, 100.0, 0x00, 0xffff); -MAKE_CONVERSIONS (u16_ab, -128.0, 127.0, 0x00, 0xffff); - void babl_base_type_u16 (void) { @@ -118,73 +115,17 @@ babl_base_type_u16 (void) "bits", 16, NULL); - babl_type_new ( - "u16-CIE-L", - "id", BABL_U16_CIE_L, - "integer", - "unsigned", - "bits", 16, - "min_val", 0.0, - "max_val", 100.0, - NULL - ); - - babl_type_new ( - "u16-CIE-ab", - "id", BABL_U16_CIE_AB, - "integer", - "unsigned", - "bits", 16, - "min_val", -50.0, - "max_val", 50.0, - NULL - ); - - babl_conversion_new ( - "babl-base: u16 to double", - "source", babl_type_id (BABL_U16), - "destination", babl_type_id (BABL_DOUBLE), + babl_type_id (BABL_U16), + babl_type_id (BABL_DOUBLE), "linear", convert_u16_double, NULL ); babl_conversion_new ( - "babl-base: double to u16", - "source", babl_type_id (BABL_DOUBLE), - "destination", babl_type_id (BABL_U16), + babl_type_id (BABL_DOUBLE), + babl_type_id (BABL_U16), "linear", convert_double_u16, NULL ); - - - babl_conversion_new ( - "babl-base: u16-CIE-L to double", - "source", babl_type_id (BABL_U16_CIE_L), - "destination", babl_type_id (BABL_DOUBLE), - "linear", convert_u16_l_double, - NULL - ); - babl_conversion_new ( - "babl-base: double to u16-CIE-L", - "source", babl_type_id (BABL_DOUBLE), - "destination", babl_type_id (BABL_U16_CIE_L), - "linear", convert_double_u16_l, - NULL - ); - - babl_conversion_new ( - "babl-base: u16-CIE-ab to double", - "source", babl_type_id (BABL_U16_CIE_AB), - "destination", babl_type_id (BABL_DOUBLE), - "linear", convert_u16_ab_double, - NULL - ); - babl_conversion_new ( - "babl-base: double to u16-CIE-ab", - "source", babl_type_id (BABL_DOUBLE), - "destination", babl_type_id (BABL_U16_CIE_AB), - "linear", convert_double_u16_ab, - NULL - ); } diff --git a/babl/base/type-u8.c b/babl/base/type-u8.c index a979021..99a4af6 100644 --- a/babl/base/type-u8.c +++ b/babl/base/type-u8.c @@ -21,6 +21,7 @@ #include #include "babl.h" +#include "babl-ids.h" static inline void convert_double_u8_scaled (double min_val, @@ -107,10 +108,6 @@ MAKE_CONVERSIONS (u8, 0.0, (255.0F/256.0F)*1.0, 0x00, 0xff); MAKE_CONVERSIONS (u8_luma, 0.0, 1.0, 16, 235); MAKE_CONVERSIONS (u8_chroma, 0.0, 1.0, 16, 240); -/* source ICC.1:2004-10 */ -MAKE_CONVERSIONS (u8_l, 0.0, 100.0, 0x00, 0xff); -MAKE_CONVERSIONS (u8_ab, -128.0, 127.0, 0x00, 0xff); - void babl_base_type_u8 (void) { @@ -140,101 +137,43 @@ babl_base_type_u8 (void) NULL ); - babl_type_new ( - "u8-CIE-L", - "id", BABL_U8_CIE_L, - "integer", - "unsigned", - "bits", 8, - "min_val", 0.0, - "max_val", 100.0, - NULL - ); - - babl_type_new ( - "u8-CIE-ab", - "id", BABL_U8_CIE_AB, - "integer", - "unsigned", - "bits", 8, - "min_val", -50.0, - "max_val", 50.0, - NULL - ); - babl_conversion_new ( - "babl-base: u8 to double", - "source", babl_type_id (BABL_U8), - "destination", babl_type_id (BABL_DOUBLE), + babl_type_id (BABL_U8), + babl_type_id (BABL_DOUBLE), "linear", convert_u8_double, NULL ); babl_conversion_new ( - "babl-base: double to u8", - "source", babl_type_id (BABL_DOUBLE), - "destination", babl_type_id (BABL_U8), + babl_type_id (BABL_DOUBLE), + babl_type_id (BABL_U8), "linear", convert_double_u8, NULL ); babl_conversion_new ( - "babl-base: u8-luma to double", - "source", babl_type_id (BABL_U8_LUMA), - "destination", babl_type_id (BABL_DOUBLE), + babl_type_id (BABL_U8_LUMA), + babl_type_id (BABL_DOUBLE), "linear", convert_u8_luma_double, NULL ); babl_conversion_new ( - "babl-base: double to u8-luma", - "source", babl_type_id (BABL_DOUBLE), - "destination", babl_type_id (BABL_U8_LUMA), + babl_type_id (BABL_DOUBLE), + babl_type_id (BABL_U8_LUMA), "linear", convert_double_u8_luma, NULL ); babl_conversion_new ( - "babl-base: u8-chroma to double", - "source", babl_type_id (BABL_U8_CHROMA), - "destination", babl_type_id (BABL_DOUBLE), + babl_type_id (BABL_U8_CHROMA), + babl_type_id (BABL_DOUBLE), "linear", convert_u8_chroma_double, NULL ); babl_conversion_new ( - "babl-base: double to u8-chroma", - "source", babl_type_id (BABL_DOUBLE), - "destination", babl_type_id (BABL_U8_CHROMA), + babl_type_id (BABL_DOUBLE), + babl_type_id (BABL_U8_CHROMA), "linear", convert_double_u8_chroma, NULL ); - - babl_conversion_new ( - "babl-base: u8-CIE-L to double", - "source", babl_type_id (BABL_U8_CIE_L), - "destination", babl_type_id (BABL_DOUBLE), - "linear", convert_u8_l_double, - NULL - ); - babl_conversion_new ( - "babl-base: double to u8-CIE-L", - "source", babl_type_id (BABL_DOUBLE), - "destination", babl_type_id (BABL_U8_CIE_L), - "linear", convert_double_u8_l, - NULL - ); - - babl_conversion_new ( - "babl-base: u8-CIE-ab to double", - "source", babl_type_id (BABL_U8_CIE_AB), - "destination", babl_type_id (BABL_DOUBLE), - "linear", convert_u8_ab_double, - NULL - ); - babl_conversion_new ( - "babl-base: double to u8-CIE-ab", - "source", babl_type_id (BABL_DOUBLE), - "destination", babl_type_id (BABL_U8_CIE_AB), - "linear", convert_double_u8_ab, - NULL - ); } diff --git a/configure.ac b/configure.ac index fc3babf..7000c06 100644 --- a/configure.ac +++ b/configure.ac @@ -52,6 +52,7 @@ docs/Makefile docs/index-static.html docs/graphics/Makefile tests/Makefile +extensions/Makefile INSTALL ) diff --git a/docs/index-static.html.in b/docs/index-static.html.in index ef27502..1f65435 100644 --- a/docs/index-static.html.in +++ b/docs/index-static.html.in @@ -222,7 +222,6 @@ cvs: cp babl/babl-pixel-format.c babl/babl-format.c cp babl/babl-pixel-format.h babl/babl-format.h cp babl/babl-classes.c babl/babl-internal.c -cp babl/base/model-cmyk.c extenstions/cmyk.c --> @@ -240,7 +239,15 @@ cp babl/base/model-cmyk.c extenstions/cmyk.c NB: the modules will be loaded from the directories pointed to by the path in reverse order, this should allow the user to override system wide definitions for types, models and formats. + +

currently the extensions are hardcoded to be installed in /home/pippin/.babl/ + and the only extensions looked for are naive-CMYK.so and CIE-Lab.so this will change + shortly. Look in babl/babl-extension.c (bottom) and extensions/Makefile.in to + change it if you so desire.

+ + + diff --git a/extensions/CIE-Lab.c b/extensions/CIE-Lab.c new file mode 100644 index 0000000..ffa8708 --- /dev/null +++ b/extensions/CIE-Lab.c @@ -0,0 +1,1234 @@ +/* babl - dynamically extendable universal pixel conversion library. + * Copyright (C) 2005, Øyvind Kolås. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include "babl.h" +#include "util.h" + +static void types (void); +static void components (void); +static void models (void); +static void conversions (void); +static void formats (void); + +int +init (void) +{ + types (); + components (); + models (); + formats (); + conversions (); + return 0; +} + +static void +components (void) +{ + babl_component_new ( "CIE L", NULL); + babl_component_new ( "CIE a", "chroma", NULL); + babl_component_new ( "CIE b", "chroma", NULL); +} + +static void +models (void) +{ + babl_model_new ( + "name", "CIE Lab", + babl_component ("CIE L"), + babl_component ("CIE a"), + babl_component ("CIE b"), + NULL); + + babl_model_new ( + "name", "CIE Lab alpha", + babl_component ("CIE L"), + babl_component ("CIE a"), + babl_component ("CIE b"), + babl_component ("A"), + NULL); +} + +/*********** cpercep.h ********* */ + +/* +Copyright (C) 1997-2002 Adam D. Moss (the "Author"). All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is fur- +nished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- +NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON- +NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the Author of the +Software shall not be used in advertising or otherwise to promote the sale, +use or other dealings in this Software without prior written authorization +from the Author. +*/ + +/* + cpercep.c: The CPercep Functions v0.9: 2002-02-10 + Adam D. Moss: adam@gimp.org + + TODO: document functions, rename erroneously-named arguments +*/ + +#ifndef __CPERCEP_H__ +#define __CPERCEP_H__ + + +void cpercep_init (void); + +void cpercep_rgb_to_space (double inr, + double ing, + double inb, + double *outr, + double *outg, + double *outb); + +void cpercep_space_to_rgb (double inr, + double ing, + double inb, + double *outr, + double *outg, + double *outb); + + +#if 0 +/* This is in the header so that it can potentially be inlined. */ +static const double +cpercep_distance_space (const double L1, const double a1, const double b1, + const double L2, const double a2, const double b2) +{ + const double Ld = L1 - L2; + const double ad = a1 - a2; + const double bd = b1 - b2; + + return (Ld*Ld + ad*ad + bd*bd); +} +#endif + + +#endif /* __CPERCEP_H__ */ + +/*********** /cpercep.h ********* */ + + + +static void +rgb_to_lab (int src_bands, + void **src, + int *src_pitch, + int dst_bands, + void **dst, + int *dst_pitch, + int n) +{ + BABL_PLANAR_SANITY + + while (n--) + { + double red = *(double*)src[0]; + double green = *(double*)src[1]; + double blue = *(double*)src[2]; + + double L, a, b; + + cpercep_rgb_to_space (red, green, blue, &L, &a, &b); + + *(double*)dst[0] = L; + *(double*)dst[1] = a; + *(double*)dst[2] = b; + + if (dst_bands > 3) /* alpha passthorugh */ + *(double*)dst[3] = (src_bands>3)?*(double*)src[3]:1.0; + + BABL_PLANAR_STEP + } +} + +static void +lab_to_rgb (int src_bands, + void **src, + int *src_pitch, + int dst_bands, + void **dst, + int *dst_pitch, + int n) +{ + BABL_PLANAR_SANITY + + while (n--) + { + double L = *(double*)src[0]; + double a = *(double*)src[1]; + double b = *(double*)src[2]; + + double red, green, blue; + + cpercep_space_to_rgb (L, a, b, &red, &green, &blue); + + *(double*)dst[0] = red; + *(double*)dst[1] = green; + *(double*)dst[2] = blue; + + if (dst_bands > 3) /* alpha passthorugh */ + *(double*)dst[3] = (src_bands>3)?*(double*)src[3]:1.0; + + BABL_PLANAR_STEP + } +} + +static void +conversions (void) +{ + + babl_conversion_new ( + babl_model ("RGBA"), + babl_model ("CIE Lab"), + "planar", rgb_to_lab, + NULL + ); + babl_conversion_new ( + babl_model ("CIE Lab"), + babl_model ("RGBA"), + "planar", lab_to_rgb, + NULL + ); + babl_conversion_new ( + babl_model ("RGB"), + babl_model ("CIE Lab"), + "planar", rgb_to_lab, + NULL + ); + babl_conversion_new ( + babl_model ("CIE Lab"), + babl_model ("RGB"), + "planar", lab_to_rgb, + NULL + ); + babl_conversion_new ( + babl_model ("RGBA"), + babl_model ("CIE Lab alpha"), + "planar", rgb_to_lab, + NULL + ); + babl_conversion_new ( + babl_model ("CIE Lab alpha"), + babl_model ("RGBA"), + "planar", lab_to_rgb, + NULL + ); + + cpercep_init (); +} + +static void +formats (void) +{ + babl_format_new ( + "CIE Lab float", + babl_model ("CIE Lab"), + + babl_type ("float"), + babl_component ("CIE L"), + babl_component ("CIE a"), + babl_component ("CIE b"), + NULL); + + babl_format_new ( + "CIE Lab u8", + babl_model ("CIE Lab"), + + babl_type ("CIE u8 L"), + babl_component ("CIE L"), + babl_type ("CIE u8 ab"), + babl_component ("CIE a"), + babl_type ("CIE u8 ab"), + babl_component ("CIE b"), + NULL); + + babl_format_new ( + "cie-lab-u16", + babl_model ("CIE Lab"), + + babl_type ("CIE u16 L"), + babl_component ("CIE L"), + babl_type ("CIE u16 ab"), + babl_component ("CIE a"), + babl_type ("CIE u16 ab"), + babl_component ("CIE b"), + NULL); +} + + +static inline void +convert_double_u8_scaled (double min_val, + double max_val, + unsigned char min, + unsigned char max, + void *src, + void *dst, + int src_pitch, + int dst_pitch, + int n) +{ + while (n--) + { + double dval = *(double *) src; + unsigned char u8val; + + if (dval < min_val) + u8val = min; + else if (dval > max_val) + u8val = max; + else + u8val = (dval-min_val) / (max_val-min_val) * (max-min) + min; + + *(unsigned char *) dst = u8val; + src += src_pitch; + dst += dst_pitch; + } +} + +static inline void +convert_u8_double_scaled (double min_val, + double max_val, + unsigned char min, + unsigned char max, + void *src, + void *dst, + int src_pitch, + int dst_pitch, + int n) +{ + while (n--) + { + int u8val = *(unsigned char *) src; + double dval; + + if (u8val < min) + dval = min_val; + else if (u8val > max) + dval = max_val; + else + dval = (u8val-min) / (double)(max-min) * (max_val-min_val) + min_val; + + (*(double *) dst) = dval; + + dst += dst_pitch; + src += src_pitch; + } +} + +#define MAKE_CONVERSIONS(name, min_val, max_val, min, max) \ +static void \ +convert_##name##_double (void *src, \ + void *dst, \ + int src_pitch, \ + int dst_pitch, \ + int n) \ +{ \ + convert_u8_double_scaled (min_val, max_val, min, max, \ + src, dst, src_pitch, dst_pitch, n); \ +} \ +static void \ +convert_double_##name (void *src, \ + void *dst, \ + int src_pitch, \ + int dst_pitch, \ + int n) \ +{ \ + convert_double_u8_scaled (min_val, max_val, min, max, \ + src, dst, src_pitch, dst_pitch, n); \ +} + +/* source ICC.1:2004-10 */ + +MAKE_CONVERSIONS (u8_l, 0.0, 100.0, 0x00, 0xff); +MAKE_CONVERSIONS (u8_ab, -128.0, 127.0, 0x00, 0xff); + +#undef MAKE_CONVERSIONS + +static void +types_u8 (void) +{ + babl_type_new ( + "CIE u8 L", + "integer", + "unsigned", + "bits", 8, + "min_val", 0.0, + "max_val", 100.0, + NULL + ); + + babl_type_new ( + "CIE u8 ab", + "integer", + "unsigned", + "bits", 8, + "min_val", -50.0, + "max_val", 50.0, + NULL + ); + + babl_conversion_new ( + babl_type ("CIE u8 L"), + babl_type ("double"), + "linear", convert_u8_l_double, + NULL + ); + babl_conversion_new ( + babl_type ("double"), + babl_type ("CIE u8 L"), + "linear", convert_double_u8_l, + NULL + ); + + babl_conversion_new ( + babl_type ("CIE u8 ab"), + babl_type ("double"), + "linear", convert_u8_ab_double, + NULL + ); + babl_conversion_new ( + babl_type ("double"), + babl_type ("CIE u8 ab"), + "linear", convert_double_u8_ab, + NULL + ); +} + +static inline void +convert_double_u16_scaled (double min_val, + double max_val, + unsigned short min, + unsigned short max, + void *src, + void *dst, + int src_pitch, + int dst_pitch, + int n) +{ + while (n--) + { + double dval = *(double *) src; + unsigned short u16val; + + if (dval < min_val) + u16val = min; + else if (dval > max_val) + u16val = max; + else + u16val = (dval-min_val) / (max_val-min_val) * (max-min) + min; + + *(unsigned short *) dst = u16val; + dst += dst_pitch; + src += src_pitch; + } +} + +static inline void +convert_u16_double_scaled (double min_val, + double max_val, + unsigned short min, + unsigned short max, + void *src, + void *dst, + int src_pitch, + int dst_pitch, + int n) +{ + while (n--) + { + int u16val = *(unsigned short*) src; + double dval; + + if (u16val < min) + dval = min_val; + else if (u16val > max) + dval = max_val; + else + dval = (u16val-min) / (double)(max-min) * (max_val-min_val) + min_val; + + (*(double *) dst) = dval; + dst += dst_pitch; + src += src_pitch; + } +} + +#define MAKE_CONVERSIONS(name, min_val, max_val, min, max) \ +static void \ +convert_##name##_double (void *src, \ + void *dst, \ + int src_pitch, \ + int dst_pitch, \ + int n) \ +{ \ + convert_u16_double_scaled (min_val, max_val, min, max, \ + src, dst, src_pitch, dst_pitch, n);\ +} \ +static void \ +convert_double_##name (void *src, \ + void *dst, \ + int src_pitch, \ + int dst_pitch, \ + int n) \ +{ \ + convert_double_u16_scaled (min_val, max_val, min, max, \ + src, dst, src_pitch, dst_pitch, n);\ +} + +MAKE_CONVERSIONS (u16_l, 0.0, 100.0, 0x00, 0xffff); +MAKE_CONVERSIONS (u16_ab, -128.0, 127.0, 0x00, 0xffff); + +#undef MAKE_CONVERSIONS + +static void +types_u16 (void) +{ + + babl_type_new ( + "CIE u16 L", + "integer", + "unsigned", + "bits", 16, + "min_val", 0.0, + "max_val", 100.0, + NULL + ); + + babl_type_new ( + "CIE u16 ab", + "id", "CIE u8 ab", + "integer", + "unsigned", + "bits", 16, + "min_val", -50.0, + "max_val", 50.0, + NULL + ); + + + babl_conversion_new ( + babl_type ("CIE u16 L"), + babl_type ("double"), + "linear", convert_u16_l_double, + NULL + ); + babl_conversion_new ( + babl_type ("double"), + babl_type ("CIE u16 L"), + "linear", convert_double_u16_l, + NULL + ); + + babl_conversion_new ( + babl_type ("CIE u16 ab"), + babl_type ("double"), + "linear", convert_u16_ab_double, + NULL + ); + babl_conversion_new ( + babl_type ("double"), + babl_type ("CIE u16 ab"), + "linear", convert_double_u16_ab, + NULL + ); +} + +static void +types (void) +{ + types_u8 (); + types_u16 (); +} + + + + +/*********** cpercep.c ********* */ + + +/* +Copyright (C) 1999-2002 Adam D. Moss (the "Author"). All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is fur- +nished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT- +NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON- +NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the Author of the +Software shall not be used in advertising or otherwise to promote the sale, +use or other dealings in this Software without prior written authorization +from the Author. +*/ + +/* + cpercep.c: The CPercep Functions v0.9: 2002-02-10 + Adam D. Moss: adam@gimp.org + + This code module concerns itself with conversion from a hard-coded + RGB colour space (sRGB by default) to CIE L*a*b* and back again with + (primarily) precision and (secondarily) speed, oriented largely + towards the purposes of quantifying the PERCEPTUAL difference between + two arbitrary RGB colours with a minimum of fuss. + + Motivation One: The author is disheartened at the amount of graphics + processing software around which uses weighted or non-weighted + Euclidean distance between co-ordinates within a (poorly-defined) RGB + space as the basis of what should really be an estimate of perceptual + difference to the human eye. Certainly it's fast to do it that way, + but please think carefully about whether your particular application + should be tolerating sloppy results for the sake of real-time response. + + Motivation Two: Lack of tested, re-usable and free code available + for this purpose. The difficulty in finding something similar to + CPercep with a free license motivated this project; I hope that this + code also serves to illustrate how to perform the + R'G'B'->XYZ->L*a*b*->XYZ->R'G'B' transformation correctly since I + was distressed to note how many of the equations and code snippets + on the net were omitting the reverse transform and/or were using + incorrectly-derived or just plain wrong constants. + + TODO: document functions, rename erroneously-named arguments +*/ + +/* defines added to make it compile outside gimp */ + +#ifndef gboolean +#define gboolean int +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + + +/* #include "config.h" */ +#include + +#ifndef __GLIBC__ +/* cbrt() is a GNU extension */ +#define cbrt(x) (pow(x, 1.0/3.0)) +#endif + +/* #include "cpercep.h" */ + + +/* defines: + + SANITY: emits warnings when passed non-sane colours (and usually + corrects them) -- useful when debugging. + + APPROX: speeds up the conversion from RGB to the colourspace by + assuming that the RGB values passed in are integral and definitely + in the range 0->255 + + SRGB: assumes that the RGB values being passed in (and out) are + destined for an sRGB-alike display device (a typical modern monitor) + -- if you change this then you'll probably want to change ASSUMED_GAMMA, + the phosphor colours and the white point definition. +*/ + +/* #define SANITY */ +/* #define APPROX */ +/* #define SRGB */ + + +#ifdef SRGB +#define ASSUMED_GAMMA (2.2F) +#else +/*#define ASSUMED_GAMMA (2.591F)*/ +#define ASSUMED_GAMMA (1.0F) +#endif + +#define REV_GAMMA ((1.0F / ASSUMED_GAMMA)) + + +/* define characteristics of the source RGB space (and the space + within which we try to behave linearly). */ + +/* Phosphor colours: */ + +/* sRGB/HDTV phosphor colours */ +static const double pxr = 0.64F; +static const double pyr = 0.33F; +static const double pxg = 0.30F; +static const double pyg = 0.60F; +static const double pxb = 0.15F; +static const double pyb = 0.06F; + +/* White point: */ + +/* D65 (6500K) (recommended but not a common display default) */ +static const double lxn = 0.312713F; +static const double lyn = 0.329016F; + +/* D50 (5000K) */ +/*static const double lxn = 0.3457F; */ +/*static const double lyn = 0.3585F; */ + +/* D55 (5500K) */ +/*static const double lxn = 0.3324F; */ +/*static const double lyn = 0.3474F; */ + +/* D93 (9300K) (a common monitor default, but poor colour reproduction) */ +/* static const double lxn = 0.2848F; */ +/* static const double lyn = 0.2932F; */ + +/* illum E (normalized) */ +/*static const double lxn = 1.0/3.0F; */ +/*static const double lyn = 1.0/3.0F; */ + +/* illum C (average sunlight) */ +/*static const double lxn = 0.3101F; */ +/*static const double lyn = 0.3162F; */ + +/* illum B (direct sunlight) */ +/*static const double lxn = 0.3484F; */ +/*static const double lyn = 0.3516F; */ + +/* illum A (tungsten lamp) */ +/*static const double lxn = 0.4476F; */ +/*static const double lyn = 0.4074F; */ + + +static const double LRAMP = 7.99959199F; + + +static double xnn, znn; + +static double powtable[256]; + + +#ifndef CLAMP +#define CLAMP(x,l,u) ((x)<(l)?(l):((x)>(u)?(u):(x))) +#endif + + +static void +init_powtable(const double gamma) +{ + int i; + +#ifndef SRGB + /* pure gamma function */ + for (i=0; i<256; i++) + { + powtable[i] = pow((i)/255.0F, gamma); + } +#else + /* sRGB gamma curve */ + for (i=0; i<11 /* 0.03928 * 255 */; i++) + { + powtable[i] = (i) / (255.0F * 12.92F); + } + for (; i<256; i++) + { + powtable[i] = pow( (((i) / 255.0F) + 0.055F) / 1.055F, 2.4F); + } +#endif +} + + +typedef double CMatrix[3][3]; +typedef double CVector[3]; + +static CMatrix Mrgb_to_xyz, Mxyz_to_rgb; + +static int +Minvert (CMatrix src, CMatrix dest) +{ + double det; + + dest[0][0] = src[1][1] * src[2][2] - src[1][2] * src[2][1]; + dest[0][1] = src[0][2] * src[2][1] - src[0][1] * src[2][2]; + dest[0][2] = src[0][1] * src[1][2] - src[0][2] * src[1][1]; + dest[1][0] = src[1][2] * src[2][0] - src[1][0] * src[2][2]; + dest[1][1] = src[0][0] * src[2][2] - src[0][2] * src[2][0]; + dest[1][2] = src[0][2] * src[1][0] - src[0][0] * src[1][2]; + dest[2][0] = src[1][0] * src[2][1] - src[1][1] * src[2][0]; + dest[2][1] = src[0][1] * src[2][0] - src[0][0] * src[2][1]; + dest[2][2] = src[0][0] * src[1][1] - src[0][1] * src[1][0]; + + det = + src[0][0] * dest[0][0] + + src[0][1] * dest[1][0] + + src[0][2] * dest[2][0]; + + if (det <= 0.0F) + { +#ifdef SANITY + g_printerr ("\n\007 XXXX det: %f\n", det); +#endif + return 0; + } + + dest[0][0] /= det; + dest[0][1] /= det; + dest[0][2] /= det; + dest[1][0] /= det; + dest[1][1] /= det; + dest[1][2] /= det; + dest[2][0] /= det; + dest[2][1] /= det; + dest[2][2] /= det; + + return 1; +} + + +static void +rgbxyzrgb_init(void) +{ + init_powtable (ASSUMED_GAMMA); + + xnn = lxn / lyn; + /* ynn taken as 1.0 */ + znn = (1.0F - (lxn + lyn)) / lyn; + + { + CMatrix MRC, MRCi; + double C1,C2,C3; + + MRC[0][0] = pxr; + MRC[0][1] = pxg; + MRC[0][2] = pxb; + MRC[1][0] = pyr; + MRC[1][1] = pyg; + MRC[1][2] = pyb; + MRC[2][0] = 1.0F - (pxr + pyr); + MRC[2][1] = 1.0F - (pxg + pyg); + MRC[2][2] = 1.0F - (pxb + pyb); + + Minvert (MRC, MRCi); + + C1 = MRCi[0][0]*xnn + MRCi[0][1] + MRCi[0][2]*znn; + C2 = MRCi[1][0]*xnn + MRCi[1][1] + MRCi[1][2]*znn; + C3 = MRCi[2][0]*xnn + MRCi[2][1] + MRCi[2][2]*znn; + + Mrgb_to_xyz[0][0] = MRC[0][0] * C1; + Mrgb_to_xyz[0][1] = MRC[0][1] * C2; + Mrgb_to_xyz[0][2] = MRC[0][2] * C3; + Mrgb_to_xyz[1][0] = MRC[1][0] * C1; + Mrgb_to_xyz[1][1] = MRC[1][1] * C2; + Mrgb_to_xyz[1][2] = MRC[1][2] * C3; + Mrgb_to_xyz[2][0] = MRC[2][0] * C1; + Mrgb_to_xyz[2][1] = MRC[2][1] * C2; + Mrgb_to_xyz[2][2] = MRC[2][2] * C3; + + Minvert (Mrgb_to_xyz, Mxyz_to_rgb); + } +} + + +static void +xyz_to_rgb (double *inx_outr, + double *iny_outg, + double *inz_outb) +{ + const double x = *inx_outr; + const double y = *iny_outg; + const double z = *inz_outb; + + *inx_outr = Mxyz_to_rgb[0][0]*x + Mxyz_to_rgb[0][1]*y + Mxyz_to_rgb[0][2]*z; + *iny_outg = Mxyz_to_rgb[1][0]*x + Mxyz_to_rgb[1][1]*y + Mxyz_to_rgb[1][2]*z; + *inz_outb = Mxyz_to_rgb[2][0]*x + Mxyz_to_rgb[2][1]*y + Mxyz_to_rgb[2][2]*z; +} + + +static void +rgb_to_xyz (double *inr_outx, + double *ing_outy, + double *inb_outz) +{ + const double r = *inr_outx; + const double g = *ing_outy; + const double b = *inb_outz; + + *inr_outx = Mrgb_to_xyz[0][0]*r + Mrgb_to_xyz[0][1]*g + Mrgb_to_xyz[0][2]*b; + *ing_outy = Mrgb_to_xyz[1][0]*r + Mrgb_to_xyz[1][1]*g + Mrgb_to_xyz[1][2]*b; + *inb_outz = Mrgb_to_xyz[2][0]*r + Mrgb_to_xyz[2][1]*g + Mrgb_to_xyz[2][2]*b; +} + + +static inline double +ffunc(const double t) +{ + if (t > 0.008856F) + { + return (cbrt(t)); + } + else + { + return (7.787F * t + 16.0F/116.0F); + } +} + + +static inline double +ffunc_inv(const double t) +{ + if (t > 0.206893F) + { + return (t * t * t); + } + else + { + return ((t - 16.0F/116.0F) / 7.787F); + } +} + + +static void +xyz_to_lab (double *inx, + double *iny, + double *inz) +{ + double L,a,b; + double ffuncY; + const double X = *inx; + const double Y = *iny; + const double Z = *inz; + + if (Y > 0.0F) + { + if (Y > 0.008856F) + { + L = (116.0F * cbrt(Y)) - 16.0F; + } + else + { + L = (Y * 903.3F); + } + +#ifdef SANITY + if (L < 0.0F) + { + g_printerr (" %f \007",(float)L); + } + + if (L > 100.0F) + { + g_printerr (" %f \007",(float)L); + } +#endif + } + else + { + L = 0.0; + } + + ffuncY = ffunc(Y); + a = 500.0F * (ffunc(X/xnn) - ffuncY); + b = 200.0F * (ffuncY - ffunc(Z/znn)); + + *inx = L; + *iny = a; + *inz = b; +} + + +static void +lab_to_xyz (double *inl, + double *ina, + double *inb) +{ + double X,Y,Z; + double P; + const double L = *inl; + const double a = *ina; + const double b = *inb; + + if (L > LRAMP) + { + P = Y = (L + 16.0F) / 116.0F; + Y = Y * Y * Y; + } + else + { + Y = L / 903.3F; + P = 7.787F * Y + 16.0F/116.0F; + } + + X = (P + a / 500.0F); + X = xnn * ffunc_inv(X); + Z = (P - b / 200.0F); + Z = znn * ffunc_inv(Z); + +#ifdef SANITY + if (X<-0.00000F) + { + if (X<-0.0001F) + g_printerr ("{badX %f {%f,%f,%f}}",X,L,a,b); + X = 0.0F; + } + if (Y<-0.00000F) + { + if (Y<-0.0001F) + g_printerr ("{badY %f}",Y); + Y = 0.0F; + } + if (Z<-0.00000F) + { + if (Z<-0.1F) + g_printerr ("{badZ %f}",Z); + Z = 0.0F; + } +#endif + + *inl = X; + *ina = Y; + *inb = Z; +} + + + +/* call this before using the CPercep function */ +void +cpercep_init (void) +{ + static gboolean initialized = FALSE; + + if (! initialized) + { + rgbxyzrgb_init(); + initialized = TRUE; + } +} + +void +cpercep_rgb_to_space (double inr, + double ing, + double inb, + double *outr, + double *outg, + double *outb) +{ +#ifdef APPROX +#ifdef SANITY + /* ADM extra sanity */ + if ((inr) > 255.0F || + (ing) > 255.0F || + (inb) > 255.0F || + (inr) < -0.0F || + (ing) < -0.0F || + (inb) < -0.0F + ) + abort(); +#endif /* SANITY */ + inr = powtable[(int)inr]; + ing = powtable[(int)ing]; + inb = powtable[(int)inb]; +#else +#ifdef SRGB + /* sRGB gamma curve */ + if (inr <= (0.03928F * 255.0F)) + inr = inr / (255.0F * 12.92F); + else + inr = pow( (inr + (0.055F * 255.0F)) / (1.055F * 255.0F), 2.4F); + + if (ing <= (0.03928F * 255.0F)) + ing = ing / (255.0F * 12.92F); + else + ing = pow( (ing + (0.055F * 255.0F)) / (1.055F * 255.0F), 2.4F); + + if (inb <= (0.03928F * 255.0F)) + inb = inb / (255.0F * 12.92F); + else + inb = pow( (inb + (0.055F * 255.0F)) / (1.055F * 255.0F), 2.4F); +#else + /* pure gamma function */ + + /* babl uses normalized RGB + inr = pow((inr)/255.0F, ASSUMED_GAMMA); + ing = pow((ing)/255.0F, ASSUMED_GAMMA); + inb = pow((inb)/255.0F, ASSUMED_GAMMA); + */ +#endif /* SRGB */ +#endif /* APPROX */ + +#ifdef SANITY + /* ADM extra sanity */ + if ((inr) > 1.0F || + (ing) > 1.0F || + (inb) > 1.0F || + (inr) < 0.0F || + (ing) < 0.0F || + (inb) < 0.0F + ) + { + g_printerr ("%%"); + /* abort(); */ + } +#endif /* SANITY */ + + rgb_to_xyz(&inr, &ing, &inb); + +#ifdef SANITY + if (inr < 0.0F || ing < 0.0F || inb < 0.0F) + { + g_printerr (" [BAD2 XYZ: %f,%f,%f]\007 ", + inr,ing,inb); + } +#endif /* SANITY */ + + xyz_to_lab(&inr, &ing, &inb); + + *outr = inr; + *outg = ing; + *outb = inb; +} + + +void +cpercep_space_to_rgb (double inr, + double ing, + double inb, + double *outr, + double *outg, + double *outb) +{ + lab_to_xyz(&inr, &ing, &inb); + +#ifdef SANITY + if (inr<-0.0F || ing<-0.0F || inb<-0.0F) + { + g_printerr (" [BAD1 XYZ: %f,%f,%f]\007 ", + inr,ing,inb); + } +#endif + + xyz_to_rgb(&inr, &ing, &inb); + + /* yes, essential. :( */ + inr = CLAMP(inr,0.0F,1.0F); + ing = CLAMP(ing,0.0F,1.0F); + inb = CLAMP(inb,0.0F,1.0F); + +#ifdef SRGB + if (inr <= 0.0030402477F) + inr = inr * (12.92F * 255.0F); + else + inr = pow(inr, 1.0F/2.4F) * (1.055F * 255.0F) - (0.055F * 255.0F); + + if (ing <= 0.0030402477F) + ing = ing * (12.92F * 255.0F); + else + ing = pow(ing, 1.0F/2.4F) * (1.055F * 255.0F) - (0.055F * 255.0F); + + if (inb <= 0.0030402477F) + inb = inb * (12.92F * 255.0F); + else + inb = pow(inb, 1.0F/2.4F) * (1.055F * 255.0F) - (0.055F * 255.0F); +#else + /* babl uses normalized RGB values + inr = 255.0F * pow(inr, REV_GAMMA); + ing = 255.0F * pow(ing, REV_GAMMA); + inb = 255.0F * pow(inb, REV_GAMMA); + */ +#endif + + *outr = inr; + *outg = ing; + *outb = inb; +} + + +#if 0 +/* EXPERIMENTAL SECTION */ + +const double +xscaler(const double start, const double end, + const double me, const double him) +{ + return start + ((end-start) * him) / (me + him); +} + + +void +mix_colours (const double L1, const double a1, const double b1, + const double L2, const double a2, const double b2, + double *rtnL, double *rtna, double *rtnb, + double mass1, double mass2) +{ + double w1, w2; + +#if 0 + *rtnL = xscaler (L1, L2, mass1, mass2); + *rtna = xscaler (a1, a2, mass1, mass2); + *rtnb = xscaler (b1, b2, mass1, mass2); +#else + +#if 1 + w1 = mass1 * L1; + w2 = mass2 * L2; +#else + w1 = mass1 * (L1*L1*L1); + w2 = mass2 * (L2*L2*L2); +#endif + + *rtnL = xscaler (L1, L2, mass1, mass2); + + if (w1 <= 0.0 && + w2 <= 0.0) + { + *rtna = + *rtnb = 0.0; +#ifdef SANITY + /* g_printerr ("\007OUCH. "); */ +#endif + } + else + { + *rtna = xscaler(a1, a2, w1, w2); + *rtnb = xscaler(b1, b2, w1, w2); + } +#endif +} +#endif /* EXPERIMENTAL SECTION */ + +/*********** /cpercep.c ********* */ diff --git a/extensions/Makefile.in b/extensions/Makefile.in new file mode 100644 index 0000000..40c798f --- /dev/null +++ b/extensions/Makefile.in @@ -0,0 +1,57 @@ +# General minimalistic compile file for self contained single +# file babl_extensions + +CFILES = $(wildcard *.c) +SOBJS = $(CFILES:.c=.so) +all: $(SOBJS) + + + +%.so: %.c + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + +# if extension needing external libraries are to be # compiled with this make +# file, each of them can be added according to the this pattern: +# extra.so: extra.c +# $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< [own compile and link flags] + +CIE-Lab.so: CIE-Lab.c + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -lm + + + + + +############################################################################# +############################################################################# +CFLAGS = -O2 -Wall +LDFLAGS = -shared -lc + +CFLAGS += `pkg-config babl --cflags` +#LDFLAGS += `pkg-config babl --libs` + + +clean: + rm -f *.so +distclean: + rm -f *.so Makefile +maintainerclean: distclean +mostlyclean: + +subdir = extensions +srcdir = @srcdir@ +top_builddir = .. +INSTALL = @INSTALL@ +SHELL = @SHELL@ + +install: user-install + #FIXME: need a proper install target as well + +user-install: all + $(INSTALL) -d /home/pippin/.babl + $(INSTALL) $(SOBJS) /home/pippin/.babl + +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) &&\ + $(SHELL) ./config.status $(subdir)/Makefile diff --git a/extensions/naive-CMYK.c b/extensions/naive-CMYK.c new file mode 100644 index 0000000..90b6749 --- /dev/null +++ b/extensions/naive-CMYK.c @@ -0,0 +1,198 @@ +/* babl - dynamically extendable universal pixel conversion library. + * Copyright (C) 2005, Øyvind Kolås. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include "babl.h" +#include "util.h" + +static void components (void); +static void models (void); +static void conversions (void); +static void formats (void); + +int +init (void) +{ + components (); + models (); + conversions (); + formats (); + + return 0; +} + +static void +components (void) +{ + babl_component_new ("cyan", NULL); + babl_component_new ("yellow", NULL); + babl_component_new ("magenta", NULL); + babl_component_new ("key", NULL); +} + +static void +models (void) +{ + babl_model_new ( + "name", "CMYK", + babl_component ("cyan"), + babl_component ("magenta"), + babl_component ("yellow"), + babl_component ("key"), + NULL + ); +} + +static void +rgb_to_cmyk (int src_bands, + void **src, + int *src_pitch, + int dst_bands, + void **dst, + int *dst_pitch, + int n) +{ + BABL_PLANAR_SANITY + + while (n--) + { + double red = *(double*)src[0]; + double green = *(double*)src[1]; + double blue = *(double*)src[2]; + + double cyan, magenta, yellow, key; + + double pullout = 1.0; + + cyan = 1.0 - red; + magenta = 1.0 - green; + yellow = 1.0 - blue; + + key = 1.0; + if (cyan < key) key = cyan; + if (magenta < key) key = magenta; + if (yellow < key) key = yellow; + + key *= pullout; + + if (key < 1.0) + { + cyan = (cyan - key) / (1.0 -key); + magenta = (magenta - key) / (1.0 -key); + yellow = (yellow - key) / (1.0 -key); + } + else + { + cyan = 0.0; + magenta = 0.0; + yellow = 0.0; + } + + *(double*)dst[0] = cyan; + *(double*)dst[1] = magenta; + *(double*)dst[2] = yellow; + *(double*)dst[3] = key; + + if (dst_bands > 4) /* alpha passthorugh */ + *(double*)dst[4] = (src_bands>3)?*(double*)src[3]:1.0; + + BABL_PLANAR_STEP + } +} + +static void +cmyk_to_rgb (int src_bands, + void **src, + int *src_pitch, + int dst_bands, + void **dst, + int *dst_pitch, + int n) +{ + BABL_PLANAR_SANITY + + while (n--) + { + double cyan = *(double*)src[0]; + double yellow = *(double*)src[1]; + double magenta = *(double*)src[2]; + double key = *(double*)src[3]; + + double red, green, blue; + + if (key < 1.0) + { + cyan = cyan * (1.0 - key) + key; + magenta = magenta * (1.0 - key) + key; + yellow = yellow * (1.0 - key) + key; + } + else + { + cyan = magenta = yellow = 1.0; + } + + red = 1.0 - cyan; + green = 1.0 - magenta; + blue = 1.0 - yellow; + + *(double*)dst[0] = red; + *(double*)dst[1] = green; + *(double*)dst[2] = blue; + + if (dst_bands > 3) /* alpha passthorugh */ + *(double*)dst[3] = (src_bands>4)?*(double*)src[4]:1.0; + + BABL_PLANAR_STEP + } +} + +static void +conversions (void) +{ + babl_conversion_new ( + babl_model ("RGBA"), + babl_model ("CMYK"), + "planar", rgb_to_cmyk, + NULL + ); + + + babl_conversion_new ( + babl_model ("CMYK"), + babl_model ("RGBA"), + "planar", cmyk_to_rgb, + NULL + ); +} + +static void +formats (void) +{ + babl_format_new ("CMYK float", + babl_model ("CMYK"), + babl_type ("float"), + babl_component ("cyan"), + babl_component ("yellow"), + babl_component ("magenta"), + babl_component ("key"), + NULL + ); +} diff --git a/tests/float_to_u8.c b/tests/float_to_u8.c index 29844c2..038bd67 100644 --- a/tests/float_to_u8.c +++ b/tests/float_to_u8.c @@ -54,14 +54,14 @@ test_float_to_rgb_u8 (void) fish = babl_fish ( babl_format_new ( "foo", - babl_model ("gray"), + babl_model ("Y"), babl_type ("float"), babl_component ("Y"), NULL ), babl_format_new ( "bar", - babl_model ("gray"), + babl_model ("Y"), babl_type ("u8"), babl_component ("Y"), NULL diff --git a/tests/grayscale_to_rgb.c b/tests/grayscale_to_rgb.c index 9e9df64..ad896da 100644 --- a/tests/grayscale_to_rgb.c +++ b/tests/grayscale_to_rgb.c @@ -40,14 +40,14 @@ test (void) fish = babl_fish ( babl_format_new ( "foo", - babl_model ("gray"), + babl_model ("Y"), babl_type ("float"), babl_component ("Y"), NULL ), babl_format_new ( "bar", - babl_model ("rgb"), + babl_model ("RGB"), babl_type ("float"), babl_component ("R"), babl_component ("G"), diff --git a/tests/rgb_to_bgr.c b/tests/rgb_to_bgr.c index 49117a2..1f47bf0 100644 --- a/tests/rgb_to_bgr.c +++ b/tests/rgb_to_bgr.c @@ -47,7 +47,7 @@ test (void) fish = babl_fish ( babl_format_new ( "foo", - babl_model ("rgb"), + babl_model ("RGB"), babl_type ("u8"), babl_component ("R"), babl_component ("G"), @@ -56,7 +56,7 @@ test (void) ), babl_format_new ( "bar", - babl_model ("rgb"), + babl_model ("RGB"), babl_type ("u8"), babl_component ("B"), babl_component ("G"), diff --git a/tests/rgb_to_lab_to_rgb.c b/tests/rgb_to_lab_to_rgb.c index 4394651..6a1e6fe 100644 --- a/tests/rgb_to_lab_to_rgb.c +++ b/tests/rgb_to_lab_to_rgb.c @@ -77,7 +77,7 @@ test (void) fish = babl_fish ( babl_format_new ( "foo", - babl_model ("rgb"), + babl_model ("RGB"), babl_type ("float"), babl_component ("R"), babl_component ("G"), diff --git a/tests/rgb_to_ycbcr.c b/tests/rgb_to_ycbcr.c index a9ce867..d06b72f 100644 --- a/tests/rgb_to_ycbcr.c +++ b/tests/rgb_to_ycbcr.c @@ -54,7 +54,7 @@ test (void) fish = babl_fish ( babl_format_new ( "foo", - babl_model ("rgb"), + babl_model ("RGB"), babl_type ("float"), babl_component ("R"), babl_component ("G"), @@ -63,7 +63,7 @@ test (void) ), babl_format_new ( "bar", - babl_model ("y'cbcr"), + babl_model ("Y'CbCr"), babl_type ("float"), babl_component ("Y'"), babl_component ("Cb"), diff --git a/tests/rgb_to_ycbcr_to_rgb.c b/tests/rgb_to_ycbcr_to_rgb.c index 6f8aa6d..0fbdf44 100644 --- a/tests/rgb_to_ycbcr_to_rgb.c +++ b/tests/rgb_to_ycbcr_to_rgb.c @@ -46,7 +46,7 @@ test (void) fish = babl_fish ( babl_format_new ( "foo", - babl_model ("rgb"), + babl_model ("RGB"), babl_type ("float"), babl_component ("R"), babl_component ("G"), @@ -55,7 +55,7 @@ test (void) ), babl_format_new ( "bar", - babl_model ("y'cbcr"), + babl_model ("Y'CbCr"), babl_type ("float"), babl_component ("Y'"), babl_component ("Cb"), diff --git a/tests/srgb_to_lab_u8.c b/tests/srgb_to_lab_u8.c index 1e2b4e2..fc7b024 100644 --- a/tests/srgb_to_lab_u8.c +++ b/tests/srgb_to_lab_u8.c @@ -48,7 +48,7 @@ test (void) int i; int OK=1; - babl_process (babl_fish ("srgb", "cie-lab-u8"), + babl_process (babl_fish ("srgb", "CIE Lab u8"), source_buf, destination_buf, PIXELS); diff --git a/tests/u8_to_float.c b/tests/u8_to_float.c index e33fb72..6249609 100644 --- a/tests/u8_to_float.c +++ b/tests/u8_to_float.c @@ -39,14 +39,14 @@ test (void) fish = babl_fish ( babl_format_new ( "foo", - babl_model ("gray"), + babl_model ("Y"), babl_type ("u8"), babl_component ("Y"), NULL ), babl_format_new ( "bar", - babl_model ("gray"), + babl_model ("Y"), babl_type ("float"), babl_component ("Y"), NULL -- 2.30.2